poll.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. from datetime import timedelta
  2. from math import ceil
  3. from django.conf import settings
  4. from django.contrib.postgres.fields import JSONField
  5. from django.db import models
  6. from django.utils import timezone
  7. class Poll(models.Model):
  8. category = models.ForeignKey("misago_categories.Category", on_delete=models.CASCADE)
  9. thread = models.OneToOneField("misago_threads.Thread", on_delete=models.CASCADE)
  10. poster = models.ForeignKey(
  11. settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL
  12. )
  13. poster_name = models.CharField(max_length=255)
  14. poster_slug = models.CharField(max_length=255)
  15. posted_on = models.DateTimeField(default=timezone.now)
  16. length = models.PositiveIntegerField(default=0)
  17. question = models.CharField(max_length=255)
  18. choices = JSONField()
  19. allowed_choices = models.PositiveIntegerField(default=1)
  20. allow_revotes = models.BooleanField(default=False)
  21. votes = models.PositiveIntegerField(default=0)
  22. is_public = models.BooleanField(default=False)
  23. def move(self, thread):
  24. if self.thread_id != thread.id:
  25. self.thread = thread
  26. self.category_id = thread.category_id
  27. self.save()
  28. self.pollvote_set.update(thread=self.thread, category_id=self.category_id)
  29. @property
  30. def ends_on(self):
  31. if self.length:
  32. return self.posted_on + timedelta(days=self.length)
  33. return None
  34. @property
  35. def is_over(self):
  36. if self.length:
  37. return timezone.now() > self.ends_on
  38. return False
  39. @property
  40. def thread_type(self):
  41. return self.category.thread_type
  42. def get_api_url(self):
  43. return self.thread_type.get_poll_api_url(self)
  44. def get_votes_api_url(self):
  45. return self.thread_type.get_poll_votes_api_url(self)
  46. def make_choices_votes_aware(self, user):
  47. if user.is_anonymous:
  48. for choice in self.choices:
  49. choice["selected"] = False
  50. return
  51. queryset = self.pollvote_set.filter(voter=user).values("choice_hash")
  52. user_votes = [v["choice_hash"] for v in queryset]
  53. for choice in self.choices:
  54. choice["selected"] = choice["hash"] in user_votes
  55. @property
  56. def has_selected_choices(self):
  57. for choice in self.choices:
  58. if choice.get("selected"):
  59. return True
  60. return False
  61. @property
  62. def view_choices(self):
  63. view_choices = []
  64. for choice in self.choices:
  65. if choice["votes"] and self.votes:
  66. proc = int(ceil(choice["votes"] * 100 / self.votes))
  67. else:
  68. proc = 0
  69. view_choices.append(
  70. {
  71. "label": choice["label"],
  72. "votes": choice["votes"],
  73. "selected": choice["selected"],
  74. "proc": proc,
  75. }
  76. )
  77. return view_choices