poll.py 2.9 KB

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