poll.py 3.0 KB

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