threadpoll.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from rest_framework import viewsets
  2. from rest_framework.decorators import detail_route
  3. from rest_framework.response import Response
  4. from django.core.exceptions import PermissionDenied
  5. from django.db import transaction
  6. from django.http import Http404
  7. from django.utils.translation import ugettext as _
  8. from misago.acl import add_acl
  9. from misago.core.shortcuts import get_int_or_404
  10. from misago.threads.models import Poll
  11. from misago.threads.permissions import (
  12. allow_delete_poll, allow_edit_poll, allow_see_poll_votes, allow_start_poll, can_start_poll)
  13. from misago.threads.serializers import (
  14. EditPollSerializer, NewPollSerializer, PollSerializer, PollVoteSerializer)
  15. from misago.threads.viewmodels import ForumThread
  16. from .pollvotecreateendpoint import poll_vote_create
  17. class ViewSet(viewsets.ViewSet):
  18. thread = None
  19. def get_thread(self, request, thread_pk):
  20. return self.thread(
  21. request,
  22. get_int_or_404(thread_pk),
  23. ).unwrap()
  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.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. request.user.lock()
  38. thread = self.get_thread(request, thread_pk)
  39. allow_start_poll(request.user, thread)
  40. try:
  41. if thread.poll and thread.poll.pk:
  42. raise PermissionDenied(_("There's already a poll in this thread."))
  43. except Poll.DoesNotExist:
  44. pass
  45. instance = Poll(
  46. thread=thread,
  47. category=thread.category,
  48. poster=request.user,
  49. poster_name=request.user.username,
  50. poster_slug=request.user.slug,
  51. poster_ip=request.user_ip,
  52. )
  53. serializer = NewPollSerializer(instance, data=request.data)
  54. if serializer.is_valid():
  55. serializer.save()
  56. add_acl(request.user, instance)
  57. for choice in instance.choices:
  58. choice['selected'] = False
  59. thread.has_poll = True
  60. thread.save()
  61. return Response(PollSerializer(instance).data)
  62. else:
  63. return Response(serializer.errors, status=400)
  64. @transaction.atomic
  65. def update(self, request, thread_pk, pk=None):
  66. request.user.lock()
  67. thread = self.get_thread(request, thread_pk)
  68. instance = self.get_poll(thread, pk)
  69. allow_edit_poll(request.user, instance)
  70. serializer = EditPollSerializer(instance, data=request.data)
  71. if serializer.is_valid():
  72. serializer.save()
  73. add_acl(request.user, instance)
  74. instance.make_choices_votes_aware(request.user)
  75. return Response(PollSerializer(instance).data)
  76. else:
  77. return Response(serializer.errors, status=400)
  78. @transaction.atomic
  79. def delete(self, request, thread_pk, pk=None):
  80. request.user.lock()
  81. thread = self.get_thread(request, thread_pk)
  82. instance = self.get_poll(thread, pk)
  83. allow_delete_poll(request.user, instance)
  84. thread.poll.delete()
  85. thread.has_poll = False
  86. thread.save()
  87. return Response({
  88. 'can_start_poll': can_start_poll(request.user, thread),
  89. })
  90. @detail_route(methods=['get', 'post'])
  91. def votes(self, request, thread_pk, pk=None):
  92. if request.method == 'POST':
  93. return self.post_votes(request, thread_pk, pk)
  94. else:
  95. return self.get_votes(request, thread_pk, pk)
  96. @transaction.atomic
  97. def post_votes(self, request, thread_pk, pk=None):
  98. request.user.lock()
  99. thread = self.get_thread(request, thread_pk)
  100. instance = self.get_poll(thread, pk)
  101. return poll_vote_create(request, thread, instance)
  102. def get_votes(self, request, thread_pk, pk=None):
  103. poll_pk = get_int_or_404(pk)
  104. try:
  105. thread = self.get_thread(request, thread_pk)
  106. if thread.poll.pk != poll_pk:
  107. raise Http404()
  108. except Poll.DoesNotExist:
  109. raise Http404()
  110. allow_see_poll_votes(request.user, thread.poll)
  111. choices = []
  112. voters = {}
  113. for choice in thread.poll.choices:
  114. choice['voters'] = []
  115. voters[choice['hash']] = choice['voters']
  116. choices.append(choice)
  117. queryset = thread.poll.pollvote_set.values(
  118. 'voter_id', 'voter_name', 'voter_slug', 'voted_on', 'choice_hash'
  119. )
  120. for voter in queryset.order_by('voter_name').iterator():
  121. voters[voter['choice_hash']].append(PollVoteSerializer(voter).data)
  122. return Response(choices)
  123. class ThreadPollViewSet(ViewSet):
  124. thread = ForumThread