Skip to content
Snippets Groups Projects
Commit adcef382 authored by florimondmanca's avatar florimondmanca
Browse files

merge participation serializers, remove unused code, change participation api...

merge participation serializers, remove unused code, change participation api endpoint, update tests
parent a2352834
No related branches found
No related tags found
No related merge requests found
......@@ -39,8 +39,7 @@ router.register('registrations', register_views.RegistrationViewSet)
# Visits views
router.register('visits', visits_views.VisitViewSet)
router.register('participants', visits_views.ParticipationsViewSet,
base_name='participants')
router.register('participations', visits_views.ParticipationsViewSet)
router.register('places', visits_views.PlaceViewSet)
# Core views
......
"""Participation API tests."""
from django.test import TestCase
from rest_framework import status
from tests.utils import HyperlinkedAPITestCase
from users.factory import UserFactory
from visits.factory import VisitFactory, ParticipationFactory
from visits.models import Participation
from visits.serializers import (ParticipationIdentifySerializer,
ParticipationWriteSerializer)
from visits.serializers import ParticipationSerializer
class ParticipationEndpointsTest(HyperlinkedAPITestCase):
"""Test access to the Participations endpoints."""
factory = ParticipationFactory
serializer_class = ParticipationWriteSerializer
serializer_class = ParticipationSerializer
@classmethod
def setUpTestData(cls):
......@@ -26,8 +23,11 @@ class ParticipationEndpointsTest(HyperlinkedAPITestCase):
def perform_create(self):
obj = self.factory.build()
url = '/api/participants/'
data = self.serialize(obj, 'post', url)
url = '/api/participations/'
data = {
'user': obj.user.id,
'visit': obj.visit.id,
}
response = self.client.post(url, data, format='json')
return response
......@@ -35,22 +35,9 @@ class ParticipationEndpointsTest(HyperlinkedAPITestCase):
self.assertRequiresAuth(self.perform_create,
expected_status_code=status.HTTP_201_CREATED)
def perform_get_id(self, obj=None):
if obj is None:
obj = self.factory.create()
url = '/api/participants/get-id/'
serializer = ParticipationIdentifySerializer(obj)
data = serializer.data
response = self.client.put(url, data, format='json')
return response
def test_get_id_authentication_required(self):
self.assertRequiresAuth(self.perform_get_id,
expected_status_code=status.HTTP_200_OK)
def perform_delete(self):
obj = self.factory.create()
url = '/api/participants/{obj.pk}/'.format(obj=obj)
url = '/api/participations/{obj.pk}/'.format(obj=obj)
response = self.client.delete(url, format='json')
return response
......@@ -58,22 +45,3 @@ class ParticipationEndpointsTest(HyperlinkedAPITestCase):
self.assertRequiresAuth(
self.perform_delete,
expected_status_code=status.HTTP_204_NO_CONTENT)
class ParticipationWriteSerializerTest(TestCase):
"""Test the write serializer for Participation."""
def setUp(self):
self.serializer = ParticipationWriteSerializer()
# Following 2 tests = regression tests. The source needs to be defined
# otherwise DRF will not convert them to User and Visit objects.
# As a result, deserialization will fail.
def test_user_id_source_is_defined(self):
self.assertEqual(self.serializer.fields['user_id'].source,
'user')
def test_visit_id_source_is_defined(self):
self.assertEqual(self.serializer.fields['visit_id'].source,
'visit')
......@@ -23,14 +23,50 @@ class PlaceSerializer(serializers.ModelSerializer):
fields = ('id', 'name', 'address', 'description')
class ParticipationWriteSerializer(serializers.ModelSerializer):
"""Serializer for adding participants to visits."""
user_id = serializers.PrimaryKeyRelatedField(
source='user',
queryset=User.objects.all(),
help_text='Identifier for the user')
visit_id = serializers.PrimaryKeyRelatedField(
source='visit',
queryset=Visit.objects.all(),
help_text='Identifier for the visit')
class Meta: # noqa
model = Participation
fields = ('id', 'user_id', 'visit_id', 'present')
class UserField(serializers.Field):
"""Custom user field used by ParticipationSerializer."""
def to_internal_value(self, user_id: int) -> User:
"""Write from an ID as a user."""
return User.objects.get(id=user_id)
def to_representation(self, user: User) -> dict:
"""Read from a user as serialized user data."""
request = self.context['request']
return UserSerializer(user, context={'request': request}).data
class ParticipationSerializer(serializers.ModelSerializer):
"""Serializer for visit participations."""
user = UserSerializer()
user = UserField(
label='Utilisateur',
help_text='Identifier for the user that participates.')
visit = serializers.PrimaryKeyRelatedField(
queryset=Visit.objects.all(),
label='Sortie',
help_text='Identifier for the associated visit.')
class Meta: # noqa
model = Participation
fields = ('id', 'user', 'present', 'accepted',)
fields = ('id', 'user', 'visit', 'present', 'accepted',)
class VisitOrganizerSerializer(serializers.ModelSerializer):
......@@ -94,31 +130,3 @@ class VisitSerializer(VisitListSerializer):
'participants', 'organizers',
'attached_files', 'image', 'fact_sheet',
'url',)
class ParticipationWriteSerializer(serializers.ModelSerializer):
"""Serializer for adding participants to visits."""
user_id = serializers.PrimaryKeyRelatedField(
source='user',
queryset=User.objects.all(),
help_text='Identifier for the user')
visit_id = serializers.PrimaryKeyRelatedField(
source='visit',
queryset=Visit.objects.all(),
help_text='Identifier for the visit')
class Meta: # noqa
model = Participation
fields = ('id', 'user_id', 'visit_id', 'present')
class ParticipationIdentifySerializer(serializers.ModelSerializer):
"""Serializer for the specialized get_id() view."""
user_id = serializers.IntegerField()
visit_id = serializers.IntegerField()
class Meta: # noqa
model = Participation
fields = ('user_id', 'visit_id',)
"""Visits API views."""
from django.shortcuts import get_object_or_404
from dry_rest_permissions.generics import DRYPermissions
from rest_framework import mixins, status, viewsets
from rest_framework.decorators import list_route
from rest_framework.response import Response
from users.models import User
from rest_framework import mixins, viewsets
from .models import Participation, Place, Visit
from .serializers import (ParticipationIdentifySerializer,
ParticipationWriteSerializer, PlaceSerializer,
from .serializers import (ParticipationSerializer, PlaceSerializer,
VisitListSerializer, VisitSerializer)
......@@ -87,6 +81,7 @@ class VisitViewSet(viewsets.ReadOnlyModelViewSet):
"date_of_birth": null,
"url": "http://localhost:8000/api/users/4/"
},
"visit": 1,
"present": null,
"accepted": null
}
......@@ -135,38 +130,48 @@ class VisitViewSet(viewsets.ReadOnlyModelViewSet):
class ParticipationsViewSet(mixins.CreateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
"""API endpoints to manage participants of visits."""
"""API endpoints to manage visit participations.
permission_classes = [DRYPermissions]
queryset = Participation.objects.all()
create:
def get_serializer_class(self):
"""Return the right serializer class for each action."""
if self.action == 'get_id':
return ParticipationIdentifySerializer
else:
return ParticipationWriteSerializer
Add a participant to a visit.
### Example payload
{
"user": 3,
"visit": 1
}
### Example response
{
"id": 5,
"visit": 1,
"user": {
"id": 3,
"email": "john.doe@example.com",
"profile_type": null,
"first_name": "John",
"last_name": "Doe",
"gender": null,
"phone_number": null,
"date_of_birth": null,
"url": "http://localhost:8000/api/users/3/"
},
"present": null,
"accepted": null
}
destroy:
@list_route(methods=['put'], url_path='get-id')
def get_id(self, request):
"""Get ID of participant from user and visit.
Remove a participant from a visit. No response data returned.
Useful to perform a DELETE request afterwards (which only accepts
a participant ID).
"""
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
user = get_object_or_404(
User, pk=serializer.validated_data['user_id'])
visit = get_object_or_404(
Visit, pk=serializer.validated_data['visit_id'])
participant = get_object_or_404(Participation,
user=user,
visit=visit)
return Response({'id': participant.id}, status=status.HTTP_200_OK)
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
queryset = Participation.objects.all()
serializer_class = ParticipationSerializer
permission_classes = [DRYPermissions]
class PlaceViewSet(viewsets.ReadOnlyModelViewSet):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment