threadpoll.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. from django.db import transaction
  2. from django.http import Http404
  3. from rest_framework import viewsets
  4. from rest_framework.decorators import detail_route
  5. from rest_framework.response import Response
  6. from misago.acl import add_acl
  7. from misago.core.shortcuts import get_int_or_404
  8. from ..models import Poll
  9. from ..permissions.polls import (
  10. allow_see_poll_votes, allow_start_poll, allow_edit_poll, allow_delete_poll, can_start_poll)
  11. from ..serializers import PollSerializer, PollVoteSerializer, NewPollSerializer, EditPollSerializer
  12. from ..viewmodels.thread import ForumThread
  13. from .pollvotecreateendpoint import poll_vote_create
  14. class ViewSet(viewsets.ViewSet):
  15. thread = None
  16. def get_thread(self, request, thread_pk, select_for_update=False):
  17. return self.thread(
  18. request,
  19. get_int_or_404(thread_pk),
  20. select_for_update=select_for_update,
  21. ).model
  22. def get_thread_for_update(self, request, thread_pk):
  23. return self.get_thread(request, thread_pk, select_for_update=True)
  24. def get_poll(self, thread, pk):
  25. try:
  26. poll_id = get_int_or_404(pk)
  27. if thread.poll.pk != poll_id:
  28. raise Http404()
  29. poll = Poll.objects.select_for_update().get(pk=thread.poll.pk)
  30. poll.thread = thread
  31. poll.category = thread.category
  32. return poll
  33. except Poll.DoesNotExist:
  34. raise Http404()
  35. @transaction.atomic
  36. def create(self, request, thread_pk):
  37. thread = self.get_thread_for_update(request, thread_pk)
  38. allow_start_poll(request.user, thread)
  39. instance = Poll(
  40. thread=thread,
  41. category=thread.category,
  42. poster=request.user,
  43. poster_name=request.user.username,
  44. poster_slug=request.user.slug,
  45. poster_ip=request.user_ip,
  46. )
  47. serializer = NewPollSerializer(instance, data=request.data)
  48. if serializer.is_valid():
  49. serializer.save()
  50. add_acl(request.user, instance)
  51. return Response(PollSerializer(instance).data)
  52. else:
  53. return Response(serializer.errors, status=400)
  54. @transaction.atomic
  55. def update(self, request, thread_pk, pk):
  56. thread = self.get_thread_for_update(request, thread_pk)
  57. instance = self.get_poll(thread, pk)
  58. allow_edit_poll(request.user, instance)
  59. serializer = EditPollSerializer(instance, data=request.data)
  60. if serializer.is_valid():
  61. serializer.save()
  62. add_acl(request.user, instance)
  63. serialized_poll = PollSerializer(instance).data
  64. instance.make_choices_votes_aware(request.user, serialized_poll['choices'])
  65. return Response(serialized_poll)
  66. else:
  67. return Response(serializer.errors, status=400)
  68. @transaction.atomic
  69. def delete(self, request, thread_pk, pk):
  70. thread = self.get_thread_for_update(request, thread_pk)
  71. instance = self.get_poll(thread, pk)
  72. allow_delete_poll(request.user, instance)
  73. thread.poll.delete()
  74. return Response({
  75. 'can_start_poll': can_start_poll(request.user, thread)
  76. })
  77. @detail_route(methods=['get', 'post'])
  78. def votes(self, request, thread_pk, pk):
  79. if request.method == 'POST':
  80. return self.post_votes(request, thread_pk, pk)
  81. else:
  82. return self.get_votes(request, thread_pk, pk)
  83. @transaction.atomic
  84. def post_votes(self, request, thread_pk, pk):
  85. thread = self.get_thread_for_update(request, thread_pk)
  86. instance = self.get_poll(thread, pk)
  87. return poll_vote_create(request, thread, instance)
  88. def get_votes(self, request, thread_pk, pk):
  89. poll_pk = get_int_or_404(pk)
  90. try:
  91. thread = self.get_thread(request, thread_pk)
  92. if thread.poll.pk != poll_pk:
  93. raise Http404()
  94. except Poll.DoesNotExist:
  95. raise Http404()
  96. allow_see_poll_votes(request.user, thread.poll)
  97. choices = []
  98. voters = {}
  99. for choice in thread.poll.choices:
  100. choice['voters'] = []
  101. voters[choice['hash']] = choice['voters']
  102. choices.append(choice)
  103. queryset = thread.poll.pollvote_set.values(
  104. 'voter_id', 'voter_name', 'voter_slug', 'voted_on', 'choice_hash')
  105. for voter in queryset.order_by('voter_name').iterator():
  106. voters[voter['choice_hash']].append(PollVoteSerializer(voter).data)
  107. return Response(choices)
  108. class ThreadPollViewSet(ViewSet):
  109. thread = ForumThread