Commit eb3d66ab authored by Staś Kycia's avatar Staś Kycia
Browse files

voting via api

parent 7c541496
Loading
Loading
Loading
Loading
+1 −1
Changes for api/serializers.py: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ class ElectionListSerializer(serializers.ModelSerializer):
class OptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Option
        fields = ['name']
        fields = ['id', 'name']
        
class ElectionSerializer(serializers.ModelSerializer):
    options = OptionSerializer(many=True, read_only=True)
+3 −2
Changes for api/urls.py: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
from django.urls import path
from api.views import ElectionListView, ElectionView, VoterView
from api.views import ElectionListView, ElectionView, VoterView, VoteAPIView

urlpatterns = [
    path("elections/", ElectionListView.as_view(), name="election-list-api"),
    path("election/<str:alias>/", ElectionView.as_view(), name="election-api"),
    path("voter/<uuid:token>/", VoterView.as_view(), name="voter-api")
    path("voter/<uuid:token>/", VoterView.as_view(), name="voter-api"),
    path("vote/<str:alias>/<str:option_id>", VoteAPIView.as_view(), name="vote-api")
]
 No newline at end of file
+51 −1
Changes for api/views.py: 51 added lines, 1 removed line.
Original line number Diff line number Diff line
from rest_framework.generics import ListAPIView, RetrieveAPIView
from rest_framework.views import APIView
from rest_framework.exceptions import PermissionDenied, ValidationError
from rest_framework import status
from rest_framework.response import Response
from django.utils import timezone
from django.db.models import Q, OuterRef, Exists
from django.shortcuts import get_object_or_404
from django.db import transaction
from django.http import HttpResponse

from elections.models import Election
from elections.models import Election, Option
from voters.models import Voter
from vote.models import Participation

@@ -70,3 +76,47 @@ class VoterView(RetrieveAPIView):
        voter = super().get_object()
        
        return voter
    
class VoteAPIView(APIView):
    def post(self, request, alias, option_id):
        token = self.request.query_params.get("token")
        if token is None:
            raise PermissionDenied("Brak tokena uwierzytelniającego!")
        try:
            voter = Voter.objects.all().filter(token=token).first()
        except:
            voter = None
        if voter is None:
            raise PermissionDenied("Nieprawidłowy token uwierzytelniający!")
        if not voter.is_verified:
            raise PermissionDenied("Konto niezweryfikowane!")

        election = get_object_or_404(Election, alias=alias)
        
        if Participation.objects.filter(voter=voter, election=election).exists():
            raise ValidationError("Już oddałeś głos w tym głosowaniu!")
        
        if not election.is_active:
            raise ValidationError("Głosowanie nie jest aktywne")
        
        if option_id == "invalid":
            if not election.allow_invalid:
                raise ValidationError("Ustawienia głosowania nie zezwalają na oddanie głosu nieważnego.")
            
        else:
            try:
                option_id = int(option_id)
                option = Option.objects.filter(pk=option_id, election=election).first()
                
                if option is None:
                    raise ValidationError("Nieprawidłowa opcja.")
            
            except:
                raise ValidationError("Nieprawidłowy identyfikator opcji.")
            
        election.cast_vote(voter, option_id)
        
        return Response(
            {"detail": "Głos pomyślnie zapisany."},
            status = status.HTTP_201_CREATED
        )
 No newline at end of file
+14 −1
Changes for elections/models.py: 14 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -58,6 +58,19 @@ class Election(models.Model):
        
        return super().save(*args, **kwargs)
        
    def cast_vote(self, voter, choice):
        if choice == 'invalid':
            self.invalid_votes += 1
            self.save()
        else:
            option = Option.objects.get(pk=choice)
            option.votes += 1
            option.save()
            
        from vote.models import Participation 
        participation = Participation(voter=voter, election=self)
        participation.save()
    
    class Meta:
        verbose_name = 'głosowanie'
        verbose_name_plural = 'głosowania'
@@ -74,4 +87,4 @@ class Option(models.Model):
    class Meta:
        verbose_name = 'opcja'
        verbose_name_plural = 'opcje'
    
        unique_together = [("name", "election")]
+2 −2
Changes for hybrid/admin.py: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -88,7 +88,7 @@ class IssueCardAdmin(admin.ModelAdmin):
        if not queryset.exists():
            return None
        card_issuer = queryset.first().card_issued_by
        return f'{card_issuer.name} ({card_issuer.email})'
        return f'{card_issuer.first_name} {card_issuer.last_name} ({card_issuer.username})'
    
    def get_urls(self):
        urls = super().get_urls()
@@ -170,7 +170,7 @@ class EnterVotesAdmin(admin.ModelAdmin):
    
    def local_votes_view(self, request, election_id):
        election = get_object_or_404(Election, pk=election_id)
        options_queryset = election.option_set.all()
        options_queryset = election.options.all()
        expected_votes_count = Participation.objects.filter(election=election, is_remote=False).count()
        
        if not election.is_hybrid or election.is_active:
Loading