diff --git a/api/event/mixins.py b/api/event/mixins.py new file mode 100644 index 0000000..d9aeaf5 --- /dev/null +++ b/api/event/mixins.py @@ -0,0 +1,5 @@ +class EventNestedMixin(object): + pass + +class ventSpecificSerializerMixin(object): + pass diff --git a/api/event/serializers.py b/api/event/serializers.py index 6195837..52d898c 100644 --- a/api/event/serializers.py +++ b/api/event/serializers.py @@ -13,10 +13,33 @@ class EventSerializer(serializers.HyperlinkedModelSerializer): # TODO rajouter des permissions class PlaceSerializer(serializers.HyperlinkedModelSerializer): + event = EventSerializer(allow_null=True) class Meta: model = Place - fields = ('url', 'id', 'name', 'description',) + fields = ('url', 'id', 'name', 'description', 'event') + + def update(self, instance, validated_data): + try: + data = validated_data.pop('event') + event = Event.objects.get_object_or_404(**data) + except KeyError: + event = None + [setattr(instance, key, value) + for key, value in validated_data.items()] + setattr(instance, 'event', event) + instance.save() + return instance + + def create(self, validated_data): + ModelClass = self.Meta.model + try: + data = validated_data.pop('event') + event = Event.objects.get_object_or_404(**data) + except KeyError: + event = None + instance = ModelClass.objects.create(event=event, **validated_data) + return instance # TODO rajouter des permissions @@ -39,19 +62,18 @@ class ActivityTemplateSerializer(serializers.HyperlinkedModelSerializer): def update(self, instance, validated_data): tags_data = validated_data.pop('tags') - [setattr(instance, key, value) for key, value in validated_data.items()] + [setattr(instance, key, value) + for key, value in validated_data.items()] instance.save() tags = [ActivityTag.objects.get_or_create(**tag_data)[0] for tag_data in tags_data] instance.tags = tags - - return instance + return instance def create(self, validated_data): tags_data = validated_data.pop('tags') activity_template = ActivityTemplate.objects.create(**validated_data) - tags = [ ActivityTag.objects.get_or_create(**tag_data)[0] + tags = [ActivityTag.objects.get_or_create(**tag_data)[0] for tag_data in tags_data] activity_template.tags = tags - return activity_template diff --git a/api/event/views.py b/api/event/views.py index fc66a42..5e3b210 100644 --- a/api/event/views.py +++ b/api/event/views.py @@ -1,9 +1,10 @@ from django.contrib.auth import get_user_model -from rest_framework.viewsets import ModelViewSet +from rest_framework.viewsets import ModelViewSet, ViewSet from api.event.serializers import EventSerializer, PlaceSerializer,\ ActivityTagSerializer, ActivityTemplateSerializer +from api.event.mixins import EventNestedMixin from event.models import Event, Place, ActivityTag, ActivityTemplate User = get_user_model() @@ -32,6 +33,21 @@ class PlaceViewSet(ModelViewSet): serializer_class = PlaceSerializer +class PlaceEventViewSet(ModelViewSet): + queryset = Place.objects.all() + serializer_class = PlaceSerializer + + def list(self, request, event_pk=None): + queryset = self.queryset.filter(event=event_pk) + page = self.paginate_queryset(queryset) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data) + + class ActivityTagViewSet(ModelViewSet): """ This viewset automatically provides `list`, `create`, `retrieve`, diff --git a/api/urls.py b/api/urls.py index 337a87f..b7c60cc 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,19 +1,25 @@ from django.conf.urls import url, include -from rest_framework.routers import DefaultRouter +from rest_framework_nested.routers import SimpleRouter, NestedSimpleRouter from api.event.views import EventViewSet, PlaceViewSet, ActivityTagViewSet,\ - ActivityTemplateViewSet + ActivityTemplateViewSet, PlaceEventViewSet # Create a router and register our viewsets with it. -router = DefaultRouter() +router = SimpleRouter() router.register(r'event', EventViewSet) router.register(r'place', PlaceViewSet) router.register(r'tag', ActivityTagViewSet) router.register(r'activitytemplate', ActivityTemplateViewSet) +# Register nested router and register someviewsets vith it +event_router = NestedSimpleRouter(router, r'event', lookup='event') +event_router.register(r'place', PlaceEventViewSet, base_name='event-names') + + # The API URLs are now determined automatically by the router. # Additionally, we include the login URLs for the browsable API. urlpatterns = [ url(r'^', include(router.urls)), + url(r'^', include(event_router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ] diff --git a/requirements.txt b/requirements.txt index 7357c33..18efed2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ channels django-bootstrap-form==3.2.1 django-widget-tweaks djangorestframework==3.6.3 +drf-nested-routers==0.90.0 django-notifications django-contrib-comments diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py new file mode 100644 index 0000000..347daa4 --- /dev/null +++ b/users/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.3 on 2017-07-18 14:22 +from __future__ import unicode_literals + +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('phone', models.CharField(blank=True, max_length=20, verbose_name='numéro de téléphone')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'utilisateur', + 'verbose_name_plural': 'utilisateurs', + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + ]