poll.py 2.8 KB

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