pollvotecreateendpoint.py 2.9 KB

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