pollvotecreateendpoint.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. from copy import deepcopy
  2. from rest_framework.response import Response
  3. from django.core.exceptions import ValidationError
  4. from django.utils import six
  5. from django.utils.translation import gettext as _
  6. from django.utils.translation import ungettext
  7. from misago.acl import add_acl
  8. from misago.threads.permissions import allow_vote_poll
  9. from misago.threads.serializers import PollSerializer
  10. def poll_vote_create(request, thread, poll):
  11. poll.make_choices_votes_aware(request.user)
  12. allow_vote_poll(request.user, poll)
  13. try:
  14. clean_votes = validate_votes(poll, request.data)
  15. except ValidationError as e:
  16. return Response({'detail': six.text_type(e)}, status=400)
  17. remove_user_votes(request.user, poll, clean_votes)
  18. set_new_votes(request, poll, clean_votes)
  19. add_acl(request.user, poll)
  20. serialized_poll = PollSerializer(poll).data
  21. poll.choices = list(map(presave_clean_choice, deepcopy(poll.choices)))
  22. poll.save()
  23. return Response(serialized_poll)
  24. def presave_clean_choice(choice):
  25. del choice['selected']
  26. return choice
  27. def validate_votes(poll, votes):
  28. try:
  29. votes_len = len(votes)
  30. if votes_len > poll.allowed_choices:
  31. message = ungettext(
  32. "This poll disallows voting for more than %(choices)s choice.",
  33. "This poll disallows voting for more than %(choices)s choices.",
  34. poll.allowed_choices,
  35. )
  36. raise ValidationError(message % {'choices': poll.allowed_choices})
  37. except TypeError:
  38. raise ValidationError(_("One or more of poll choices were invalid."))
  39. valid_choices = [c['hash'] for c in poll.choices]
  40. clean_votes = []
  41. for vote in votes:
  42. if vote in valid_choices:
  43. clean_votes.append(vote)
  44. if len(clean_votes) != len(votes):
  45. raise ValidationError(_("One or more of poll choices were invalid."))
  46. if not len(votes):
  47. raise ValidationError(_("You have to make a choice."))
  48. return clean_votes
  49. def remove_user_votes(user, poll, final_votes):
  50. removed_votes = []
  51. for choice in poll.choices:
  52. if choice['selected'] and choice['hash'] not in final_votes:
  53. poll.votes -= 1
  54. choice['votes'] -= 1
  55. choice['selected'] = False
  56. removed_votes.append(choice['hash'])
  57. if removed_votes:
  58. poll.pollvote_set.filter(voter=user, choice_hash__in=removed_votes).delete()
  59. def set_new_votes(request, poll, final_votes):
  60. for choice in poll.choices:
  61. if not choice['selected'] and choice['hash'] in final_votes:
  62. poll.votes += 1
  63. choice['votes'] += 1
  64. choice['selected'] = True
  65. poll.pollvote_set.create(
  66. category=poll.category,
  67. thread=poll.thread,
  68. voter=request.user,
  69. voter_name=request.user.username,
  70. voter_slug=request.user.slug,
  71. choice_hash=choice['hash'],
  72. voter_ip=request.user_ip,
  73. )