poll.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. from django.core.urlresolvers import reverse
  2. from django.utils.crypto import get_random_string
  3. from django.utils.translation import ugettext as _, ungettext
  4. from rest_framework import serializers
  5. from ..models import Poll
  6. MAX_POLL_OPTIONS = 16
  7. class PollSerializer(serializers.ModelSerializer):
  8. acl = serializers.SerializerMethodField()
  9. choices = serializers.SerializerMethodField()
  10. api = serializers.SerializerMethodField()
  11. url = serializers.SerializerMethodField()
  12. class Meta:
  13. model = Poll
  14. fields = (
  15. 'poster_name',
  16. 'poster_slug',
  17. 'posted_on',
  18. 'length',
  19. 'question',
  20. 'allowed_choices',
  21. 'allow_revotes',
  22. 'votes',
  23. 'is_public',
  24. 'acl',
  25. 'choices',
  26. 'api',
  27. 'url',
  28. )
  29. def get_api(self, obj):
  30. return {
  31. 'index': reverse('misago:api:thread-poll-list', kwargs={
  32. 'thread_pk': obj.thread_id
  33. }),
  34. }
  35. def get_url(self, obj):
  36. return {
  37. 'poster': self.get_last_poster_url(obj),
  38. }
  39. def get_last_poster_url(self, obj):
  40. if obj.poster_id:
  41. return reverse('misago:user', kwargs={
  42. 'slug': obj.poster_slug,
  43. 'pk': obj.poster_id,
  44. })
  45. else:
  46. return None
  47. def get_acl(self, obj):
  48. try:
  49. return obj.acl
  50. except AttributeError:
  51. return None
  52. def get_choices(self, obj):
  53. return obj.choices
  54. class EditPollSerializer(serializers.ModelSerializer):
  55. length = serializers.IntegerField(required=True, min_value=0, max_value=180)
  56. question = serializers.CharField(required=True, max_length=255)
  57. allowed_choices = serializers.IntegerField(required=True, min_value=1)
  58. choices = serializers.ListField(
  59. allow_empty=False,
  60. child=serializers.DictField(),
  61. )
  62. class Meta:
  63. model = Poll
  64. fields = (
  65. 'length',
  66. 'question',
  67. 'allowed_choices',
  68. 'allow_revotes',
  69. 'choices',
  70. )
  71. def validate_choices(self, choices):
  72. clean_choices = list(map(self.clean_choice, choices))
  73. def clean_choice(self, choice):
  74. clean_choice = {
  75. 'hash': choice.get('hash', get_random_string(12)),
  76. 'label': choice.get('label', ''),
  77. }
  78. serializer = PollChoiceSerializer(data=clean_choice)
  79. if not serializer.is_valid():
  80. raise serializers.ValidationError(_("One or more poll choices are invalid."))
  81. return serializer.data
  82. def validate_choices_num(self, choices):
  83. total_choices = len(choices)
  84. if total_choices < 2:
  85. raise serializers.ValidationError(_("You need to add at least two choices to a poll."))
  86. if total_choices > MAX_POLL_OPTIONS:
  87. message = ungettext(
  88. "You can't add more than %(limit_value)s option to a single poll (added %(show_value)s).",
  89. "You can't add more than %(limit_value)s options to a single poll (added %(show_value)s).",
  90. MAX_POLL_OPTIONS)
  91. raise serializers.ValidationError(message % {
  92. 'limit_value': MAX_POLL_OPTIONS,
  93. 'show_value': total_choices
  94. })
  95. def validate(self, data):
  96. if data['allowed_choices'] > len(data['choices']):
  97. raise serializers.ValidationError(
  98. _("Number of allowed choices can't be greater than number of all choices."))
  99. return data
  100. class NewPollSerializer(EditPollSerializer):
  101. class Meta:
  102. model = Poll
  103. fields = (
  104. 'length',
  105. 'question',
  106. 'allowed_choices',
  107. 'allow_revotes',
  108. 'is_public',
  109. 'choices',
  110. )
  111. def validate_choices(self, choices):
  112. clean_choices = list(map(self.clean_choice, choices))
  113. self.validate_choices_num(clean_choices)
  114. for choice in clean_choices:
  115. choice.update({
  116. 'hash': get_random_string(12),
  117. 'votes': 0
  118. })
  119. return clean_choices
  120. class PollChoiceSerializer(serializers.Serializer):
  121. hash = serializers.CharField(required=True, min_length=12, max_length=12)
  122. label = serializers.CharField(required=True, max_length=255)