poll.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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.pollvote_set.update(thread=thread)
  31. self.save()
  32. @property
  33. def ends_on(self):
  34. if self.length:
  35. return self.posted_on + timedelta(days=self.length)
  36. return None
  37. @property
  38. def is_over(self):
  39. if self.length:
  40. return timezone.now() > self.ends_on
  41. return False
  42. @property
  43. def thread_type(self):
  44. return self.category.thread_type
  45. def get_api_url(self):
  46. return self.thread_type.get_poll_api_url(self)
  47. def get_votes_api_url(self):
  48. return self.thread_type.get_poll_votes_api_url(self)
  49. def make_choices_votes_aware(self, user):
  50. if user.is_anonymous():
  51. for choice in self.choices:
  52. choice['selected'] = False
  53. return
  54. queryset = self.pollvote_set.filter(voter=user).values('choice_hash')
  55. user_votes = [v['choice_hash'] for v in queryset]
  56. for choice in self.choices:
  57. choice['selected'] = choice['hash'] in user_votes
  58. @property
  59. def has_selected_choices(self):
  60. for choice in self.choices:
  61. if choice.get('selected'):
  62. return True
  63. return False
  64. @property
  65. def view_choices(self):
  66. view_choices = []
  67. for choice in self.choices:
  68. if choice['votes'] and self.votes:
  69. proc = int(ceil(choice['votes'] * 100 / self.votes))
  70. else:
  71. proc = 0
  72. view_choices.append({
  73. 'label': choice['label'],
  74. 'votes': choice['votes'],
  75. 'selected': choice['selected'],
  76. 'proc': proc
  77. })
  78. return view_choices