pollvotecreateendpoint.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. from copy import deepcopy
  2. from django.core.exceptions import ValidationError
  3. from django.utils import six
  4. from django.utils.translation import gettext as _
  5. from django.utils.translation import ungettext
  6. from rest_framework.response import Response
  7. from misago.acl import add_acl
  8. from misago.threads.permissions.polls 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. raise ValidationError(message % {'choices': poll.allowed_choices})
  36. except TypeError:
  37. raise ValidationError(_("One or more of poll choices were invalid."))
  38. valid_choices = [c['hash'] for c in poll.choices]
  39. clean_votes = []
  40. for vote in votes:
  41. if vote in valid_choices:
  42. clean_votes.append(vote)
  43. if len(clean_votes) != len(votes):
  44. raise ValidationError(_("One or more of poll choices were invalid."))
  45. if not len(votes):
  46. raise ValidationError(_("You have to make a choice."))
  47. return clean_votes
  48. def remove_user_votes(user, poll, final_votes):
  49. removed_votes = []
  50. for choice in poll.choices:
  51. if choice['selected'] and choice['hash'] not in final_votes:
  52. poll.votes -= 1
  53. choice['votes'] -= 1
  54. choice['selected'] = False
  55. removed_votes.append(choice['hash'])
  56. if removed_votes:
  57. poll.pollvote_set.filter(voter=user, choice_hash__in=removed_votes).delete()
  58. def set_new_votes(request, poll, final_votes):
  59. for choice in poll.choices:
  60. if not choice['selected'] and choice['hash'] in final_votes:
  61. poll.votes += 1
  62. choice['votes'] += 1
  63. choice['selected'] = True
  64. poll.pollvote_set.create(
  65. category=poll.category,
  66. thread=poll.thread,
  67. voter=request.user,
  68. voter_name=request.user.username,
  69. voter_slug=request.user.slug,
  70. choice_hash=choice['hash'],
  71. voter_ip=request.user_ip
  72. )