poll.py 2.9 KB

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