NDOJ/judge/views/pagevote.py
2024-01-13 18:23:37 -06:00

107 lines
3 KiB
Python

from django.contrib.auth.decorators import login_required
from django.db import IntegrityError
from django.db.models import F
from django.http import (
Http404,
HttpResponse,
HttpResponseBadRequest,
HttpResponseForbidden,
)
from django.utils.translation import gettext as _
from judge.models.pagevote import PageVote, PageVoteVoter
from django.views.generic.base import TemplateResponseMixin
from django.views.generic.detail import SingleObjectMixin
from django.views.generic import View, ListView
from django_ratelimit.decorators import ratelimit
from django.conf import settings
__all__ = [
"upvote_page",
"downvote_page",
"PageVoteDetailView",
"PageVoteListView",
]
@ratelimit(key="user", rate=settings.RL_VOTE)
@login_required
def vote_page(request, delta):
if abs(delta) != 1:
return HttpResponseBadRequest(
_("Messing around, are we?"), content_type="text/plain"
)
if request.method != "POST":
return HttpResponseForbidden()
if "id" not in request.POST:
return HttpResponseBadRequest()
if (
not request.user.is_staff
and not request.profile.submission_set.filter(
points=F("problem__points")
).exists()
):
return HttpResponseBadRequest(
_("You must solve at least one problem before you can vote."),
content_type="text/plain",
)
try:
pagevote_id = int(request.POST["id"])
except ValueError:
return HttpResponseBadRequest()
else:
if not PageVote.objects.filter(id=pagevote_id).exists():
raise Http404()
vote = PageVoteVoter()
vote.pagevote_id = pagevote_id
vote.voter = request.profile
vote.score = delta
try:
vote.save()
except IntegrityError:
try:
vote = PageVoteVoter.objects.get(
pagevote_id=pagevote_id, voter=request.profile
)
except PageVoteVoter.DoesNotExist:
raise Http404()
vote.delete()
PageVote.objects.filter(id=pagevote_id).update(score=F("score") - vote.score)
else:
PageVote.objects.filter(id=pagevote_id).update(score=F("score") + delta)
_dirty_vote_score(pagevote_id, request.profile)
return HttpResponse("success", content_type="text/plain")
def upvote_page(request):
return vote_page(request, 1)
def downvote_page(request):
return vote_page(request, -1)
class PageVoteDetailView(TemplateResponseMixin, SingleObjectMixin, View):
pagevote_page = None
def get_pagevote_page(self):
if self.pagevote_page is None:
raise NotImplementedError()
return self.pagevote_page
def get_context_data(self, **kwargs):
context = super(PageVoteDetailView, self).get_context_data(**kwargs)
context["pagevote"] = self.object.get_or_create_pagevote()
return context
def _dirty_vote_score(pagevote_id, profile):
pv = PageVote(id=pagevote_id)
pv.vote_score.dirty(pv, profile)