Skip to content

Commit

Permalink
manage category tree, areas and api settings
Browse files Browse the repository at this point in the history
  • Loading branch information
submarcos committed Jul 5, 2024
1 parent 72b3f98 commit ca210bd
Show file tree
Hide file tree
Showing 14 changed files with 302 additions and 241 deletions.
12 changes: 11 additions & 1 deletion backend/project/accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Generated by Django 5.0.6 on 2024-06-28 13:23
# Generated by Django 5.0.6 on 2024-07-04 14:28

import django.contrib.postgres.functions
import django.db.models.functions.datetime
import django.utils.timezone
from django.db import migrations, models
Expand Down Expand Up @@ -41,6 +42,15 @@ class Migration(migrations.Migration):
verbose_name="superuser status",
),
),
(
"uuid",
models.UUIDField(
db_default=django.contrib.postgres.functions.RandomUUID(),
db_index=True,
editable=False,
unique=True,
),
),
(
"email",
models.EmailField(
Expand Down
24 changes: 0 additions & 24 deletions backend/project/accounts/migrations/0002_user_uuid.py

This file was deleted.

2 changes: 1 addition & 1 deletion backend/project/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ def filter_fields(self, qs):

class Meta:
model = Observation
fields = ["event_date", "observation_subtype", "fields"]
fields = ["event_date", "category", "fields"]
58 changes: 53 additions & 5 deletions backend/project/api/serializers/common.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,58 @@
from rest_framework import serializers
from rest_framework.reverse import reverse

from project.api.serializers.observations import ObservationTypeSerializer
from project.api.serializers.observations import (
AreaSerializer,
ObservationCategorySerializer,
)


class TokenEndpointsSerializer(serializers.Serializer):
token = serializers.SerializerMethodField()
token_refresh = serializers.SerializerMethodField()
token_verify = serializers.SerializerMethodField()

def get_token(self, obj):
return self.context["request"].build_absolute_uri(
reverse("api:token_obtain_pair")
)

def get_token_refresh(self, obj):
return self.context["request"].build_absolute_uri(reverse("api:token_refresh"))

def get_token_verify(self, obj):
return self.context["request"].build_absolute_uri(reverse("api:token_verify"))


class UserEndpointsSerializer(serializers.Serializer):
me = serializers.SerializerMethodField()
observations = serializers.SerializerMethodField()

def get_me(self, obj):
return self.context["request"].build_absolute_uri(reverse("api:me"))

def get_observations(self, obj):
return self.context["request"].build_absolute_uri(
reverse("api:account-observations-list")
)


class EndpointsSerializer(serializers.Serializer):
signup = serializers.SerializerMethodField()
observations = serializers.SerializerMethodField()
user = UserEndpointsSerializer()
token = TokenEndpointsSerializer()

def get_signup(self, obj):
return self.context["request"].build_absolute_uri(reverse("api:signup"))

def get_observations(self, obj):
return self.context["request"].build_absolute_uri(
reverse("api:observations-list")
)


class SettingsSerializer(serializers.Serializer):
observation_types = ObservationTypeSerializer(many=True, read_only=True)
observation_public_url = serializers.HyperlinkedIdentityField(
view_name="api:observations-list"
)
categories = ObservationCategorySerializer(many=True)
areas = AreaSerializer(many=True)
endpoints = EndpointsSerializer()
46 changes: 24 additions & 22 deletions backend/project/api/serializers/observations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,25 @@
from rest_framework_gis import serializers as gis_serializers
from sorl.thumbnail import get_thumbnail

from project.observations.models import (
Media,
Observation,
ObservationSubType,
ObservationType,
)
from project.observations.models import Area, Media, Observation, ObservationCategory


class ObservationSubTypeSerializer(serializers.ModelSerializer):
class ObservationCategorySerializer(serializers.ModelSerializer):

class Meta:
model = ObservationSubType
model = ObservationCategory
fields = (
"id",
"label",
"description",
"pictogram",
"children",
)


class ObservationTypeSerializer(serializers.ModelSerializer):
sub_types = ObservationSubTypeSerializer(many=True)

class Meta:
model = ObservationType
fields = ("id", "label", "description", "pictogram", "sub_types")
def get_fields(self):
fields = super().get_fields()
fields["children"] = ObservationCategorySerializer(many=True)
return fields


class ThumbnailSerializer(serializers.Serializer):
Expand Down Expand Up @@ -71,9 +65,6 @@ class Meta:

class ObservationMixin(DynamicFieldsMixin, gis_serializers.GeoFeatureModelSerializer):
source = serializers.SlugRelatedField("label", read_only=True)
subtype = serializers.SlugRelatedField(
"label", source="observation_subtype", read_only=True
)

class Meta:
model = Observation
Expand All @@ -84,20 +75,31 @@ class Meta:
"comments",
"event_date",
"source",
"subtype",
"category",
)
write_only_fields = ("observation_subtype__id",)
write_only_fields = ("category__id",)


class ObservationListSerializer(ObservationMixin):
first_photo = MediaSerializer(read_only=True)
main_picture = MediaSerializer(read_only=True)

class Meta(ObservationMixin.Meta):
fields = ObservationMixin.Meta.fields + ("first_photo",)
fields = ObservationMixin.Meta.fields + ("main_picture",)


class ObservationDetailSerializer(ObservationMixin):
medias = MediaSerializer(many=True, read_only=True)

class Meta(ObservationMixin.Meta):
fields = ObservationMixin.Meta.fields + ("medias",)


class AreaSerializer(serializers.ModelSerializer):
bbox = serializers.SerializerMethodField()

def get_bbox(self, obj):
return [obj.north_west.coords, obj.south_east.coords]

class Meta:
model = Area
fields = ("id", "name", "bbox")
2 changes: 1 addition & 1 deletion backend/project/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"post": "signup",
}
),
name="me",
name="signup",
),
path("api/", include(router.urls)),
]
36 changes: 19 additions & 17 deletions backend/project/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,39 @@
UpdateModelMixin,
)
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.viewsets import GenericViewSet

from project.accounts.models import User
from project.api.filters import ObservationFilterSet
from project.api.serializers.accounts import AccountSerializer
from project.api.serializers.common import SettingsSerializer
from project.api.serializers.common import EndpointsSerializer, SettingsSerializer
from project.api.serializers.observations import (
ObservationDetailSerializer,
ObservationListSerializer,
ObservationTypeSerializer,
)
from project.observations.models import Observation, ObservationType
from project.observations.models import Area, Observation, ObservationCategory


class SettingsApiView(GenericAPIView):
serializer_class = SettingsSerializer

def get(self, request):
data = {}
observation_types = ObservationType.objects.prefetch_related("sub_types").all()
observation_types_serialized = ObservationTypeSerializer(
observation_types, many=True, context={"request": request}
serializer = self.get_serializer(
{
"areas": Area.objects.all(),
"endpoints": EndpointsSerializer(
context=self.get_serializer_context()
).data,
"categories": ObservationCategory.objects.filter(depth=1),
}
)
data["observation_types"] = observation_types_serialized.data
data["observation_public_url"] = reverse(
"api:observations-list", request=request
)
return Response(data)
return Response(serializer.data)


class ObservationViewSet(viewsets.ReadOnlyModelViewSet):
queryset = (
Observation.objects.all()
.select_related("source", "observation_subtype__observation_type")
.select_related("source", "category")
.prefetch_related("medias")
)
filter_backends = (DjangoFilterBackend,)
Expand All @@ -62,12 +60,16 @@ class AccountViewSet(
):
queryset = User.objects.all()
serializer_class = AccountSerializer
permission_classes = [permissions.IsAuthenticated]

def get_object(self):
return self.request.user

@action(detail=False, methods=["post"], permission_classes=[permissions.AllowAny])
def get_permissions(self):
if self.action == "signup":
return [permissions.AllowAny()]
return [permissions.IsAuthenticated()]

@action(detail=False, methods=["post"])
def signup(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
Expand All @@ -83,7 +85,7 @@ class AccountObservationViewset(viewsets.ModelViewSet):
def get_queryset(self):
return (
self.request.user.observations.all()
.select_related("source", "observation_subtype__observation_type")
.select_related("source", "category")
.prefetch_related("medias")
)

Expand Down
Loading

0 comments on commit ca210bd

Please sign in to comment.