From 5d774e9ba602b8896c7d64846a56a85b4aef0557 Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:38:51 +0300 Subject: [PATCH 1/8] Document address API parameters --- services/api.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/services/api.py b/services/api.py index 0b3406e6..0c47c0c1 100644 --- a/services/api.py +++ b/services/api.py @@ -15,6 +15,7 @@ from django.utils import timezone, translation from django.utils.module_loading import import_string from django_filters.rest_framework import DjangoFilterBackend +from drf_spectacular.utils import extend_schema, OpenApiParameter from modeltranslation.translator import NotRegistered, translator from mptt.utils import drilldown_tree_for_node from munigeo import api as munigeo_api @@ -1196,6 +1197,63 @@ def get_queryset(self): register_view(AdministrativeDivisionViewSet, "administrative_division") +@extend_schema( + parameters=[ + OpenApiParameter( + name="street", + location=OpenApiParameter.QUERY, + description="Filter by street name.", + required=False, + type=str, + ), + OpenApiParameter( + name="municipality", + location=OpenApiParameter.QUERY, + description="Filter by municipality name or OCD ID.", + required=False, + type=str, + ), + OpenApiParameter( + name="number", + location=OpenApiParameter.QUERY, + description="Filter by building number.", + required=False, + type=str, + ), + OpenApiParameter( + name="lat", + location=OpenApiParameter.QUERY, + description="Filter by location. Give latitude in WGS84 system. If this parameter is given also the 'lon' " + "parameter is required.", + required=False, + type=float, + ), + OpenApiParameter( + name="lon", + location=OpenApiParameter.QUERY, + description="Filter by location. Give longitude in WGS84 system. If this parameter is given also the 'lat' " + "parameter is required.", + required=False, + type=float, + ), + OpenApiParameter( + name="distance", + location=OpenApiParameter.QUERY, + description="The maximum distance from the provided location, defined by the lat and lon parameters. " + "If this parameter is given also the 'lat' and 'lon' parameters are required.", + required=False, + type=float, + ), + OpenApiParameter( + name="bbox", + location=OpenApiParameter.QUERY, + description="Bounding box in the format 'left,bottom,right,top'. " + "Values must be floating points or integers.", + required=False, + type=str, + ), + ], +) class AddressViewSet(munigeo_api.AddressViewSet): serializer_class = munigeo_api.AddressSerializer From b9d9321ee2e21dd93fcce70d91a892c30f2048e5 Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:41:26 +0300 Subject: [PATCH 2/8] Document administrative division API parameters --- services/api.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/services/api.py b/services/api.py index 0c47c0c1..863c7d26 100644 --- a/services/api.py +++ b/services/api.py @@ -1172,6 +1172,75 @@ def to_representation(self, obj): return ret +@extend_schema( + parameters=[ + OpenApiParameter( + name="type", + location=OpenApiParameter.QUERY, + description="Filter by administrative division type or type ID.", + required=False, + type=str, + ), + OpenApiParameter( + name="lat", + location=OpenApiParameter.QUERY, + description="Filter by location. Give latitude in WGS84 system. If this parameter is given also the 'lon' " + "parameter is required.", + required=False, + type=float, + ), + OpenApiParameter( + name="lon", + location=OpenApiParameter.QUERY, + description="Filter by location. Give longitude in WGS84 system. If this parameter is given also the 'lat' " + "parameter is required.", + required=False, + type=float, + ), + OpenApiParameter( + name="input", + location=OpenApiParameter.QUERY, + description="Filter by partial match of name.", + required=False, + type=str, + ), + OpenApiParameter( + name="ocd_id", + location=OpenApiParameter.QUERY, + description="Filter by OCD ID.", + required=False, + type=str, + ), + OpenApiParameter( + name="geometry", + location=OpenApiParameter.QUERY, + description="Display administrative division boundary.", + required=False, + type=bool, + ), + OpenApiParameter( + name="origin_id", + location=OpenApiParameter.QUERY, + description="Filter by origin ID.", + required=False, + type=str, + ), + OpenApiParameter( + name="municipality", + location=OpenApiParameter.QUERY, + description="Filter by municipality.", + required=False, + type=str, + ), + OpenApiParameter( + name="date", + location=OpenApiParameter.QUERY, + description="Filter divisions based on their validity date. Format: YYYY-MM-DD.", + required=False, + type=str, + ), + ] +) class AdministrativeDivisionViewSet(munigeo_api.AdministrativeDivisionViewSet): serializer_class = AdministrativeDivisionSerializer From 7f26477475d199608a0baea8870a3eec7b8968e6 Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:51:27 +0300 Subject: [PATCH 3/8] Document service node API parameters --- services/api.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/services/api.py b/services/api.py index 863c7d26..6a8e3941 100644 --- a/services/api.py +++ b/services/api.py @@ -533,6 +533,24 @@ class Meta: exclude = ["unit", "id"] +@extend_schema( + parameters=[ + OpenApiParameter( + name="id", + location=OpenApiParameter.QUERY, + description="Filter by ID or list of IDs.", + required=False, + type=str, + ), + OpenApiParameter( + name="ancestor", + location=OpenApiParameter.QUERY, + description="Filter by ancestor ID.", + required=False, + type=str, + ), + ] +) class ServiceNodeViewSet(JSONAPIViewSet, viewsets.ReadOnlyModelViewSet): queryset = ServiceNode.objects.all() serializer_class = ServiceNodeSerializer From ef9a21d0ec13c7c65b4e7ee294e9e15693ec66a5 Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:12:44 +0300 Subject: [PATCH 4/8] Document service API parameters --- services/api.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/services/api.py b/services/api.py index 6a8e3941..c341e726 100644 --- a/services/api.py +++ b/services/api.py @@ -578,6 +578,17 @@ def get_queryset(self): register_view(ServiceNodeViewSet, "service_node") +@extend_schema( + parameters=[ + OpenApiParameter( + name="id", + location=OpenApiParameter.QUERY, + description="Filter by ID or list of IDs.", + required=False, + type=str, + ), + ] +) class ServiceViewSet(JSONAPIViewSet, viewsets.ReadOnlyModelViewSet): queryset = Service.objects.all() serializer_class = ServiceSerializer From cf6330fd928b4dc3259d3cf79ebee70f22622055 Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:17:17 +0300 Subject: [PATCH 5/8] Document unit API parameters --- services/api.py | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/services/api.py b/services/api.py index c341e726..c613ba82 100644 --- a/services/api.py +++ b/services/api.py @@ -842,6 +842,59 @@ def render(self, data, media_type=None, renderer_context=None): return render_to_string("kml.xml", resp) +@extend_schema( + parameters=[ + OpenApiParameter( + name="id", + location=OpenApiParameter.QUERY, + description="Filter by ID or list of IDs.", + required=False, + type=str, + ), + OpenApiParameter( + name="municipality", + location=OpenApiParameter.QUERY, + description="Filter by municipality name or OCD ID.", + required=False, + type=str, + ), + OpenApiParameter( + name="organization", + location=OpenApiParameter.QUERY, + description="Filter by organization UUID.", + required=False, + type=str, + ), + OpenApiParameter( + name="city_as_department", + location=OpenApiParameter.QUERY, + description="Filter by city UUID.", + required=False, + type=str, + ), + OpenApiParameter( + name="provider_type", + location=OpenApiParameter.QUERY, + description="Filter by provider type numeric value.", + required=False, + type=int, + ), + OpenApiParameter( + name="provider_type__not", + location=OpenApiParameter.QUERY, + description="Exclude by provider type numeric value.", + required=False, + type=int, + ), + OpenApiParameter( + name="level", + location=OpenApiParameter.QUERY, + description="Filter by level.", + required=False, + type=str, + ), + ] +) class UnitViewSet( munigeo_api.GeoModelAPIView, JSONAPIViewSet, viewsets.ReadOnlyModelViewSet ): @@ -876,6 +929,12 @@ def get_queryset(self): id_list = filters["id"].split(",") queryset = queryset.filter(id__in=id_list) + for f in filters: + if f.startswith("extra__"): + queryset = queryset.filter( + **{f: int(filters[f]) if filters[f].isnumeric() else filters[f]} + ) + if "municipality" in filters: val = filters["municipality"].lower().strip() if len(val) > 0: From bed635a791e8720e3ba70d8c50ca80ee6d810192 Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:51:34 +0300 Subject: [PATCH 6/8] Reduce OpenApi parameter duplication Refactor OpenAPI parameters to constants to reduce duplication. --- services/api.py | 246 +++++++------------------------- services/open_api_parameters.py | 174 ++++++++++++++++++++++ 2 files changed, 223 insertions(+), 197 deletions(-) create mode 100644 services/open_api_parameters.py diff --git a/services/api.py b/services/api.py index c613ba82..e0785557 100644 --- a/services/api.py +++ b/services/api.py @@ -15,7 +15,7 @@ from django.utils import timezone, translation from django.utils.module_loading import import_string from django_filters.rest_framework import DjangoFilterBackend -from drf_spectacular.utils import extend_schema, OpenApiParameter +from drf_spectacular.utils import extend_schema from modeltranslation.translator import NotRegistered, translator from mptt.utils import drilldown_tree_for_node from munigeo import api as munigeo_api @@ -42,6 +42,29 @@ UnitServiceDetails, ) from services.models.unit import ORGANIZER_TYPES, PROVIDER_TYPES +from services.open_api_parameters import ( + ANCESTOR_ID_PARAMETER, + BBOX_PARAMETER, + BUILDING_NUMBER_PARAMETER, + CITY_AS_DEPARTMENT_PARAMETER, + DATE_PARAMETER, + DISTANCE_PARAMETER, + DIVISION_TYPE_PARAMETER, + GEOMETRY_PARAMETER, + ID_PARAMETER, + INPUT_PARAMETER, + LATITUDE_PARAMETER, + LEVEL_PARAMETER, + LONGITUDE_PARAMETER, + MUNICIPALITY_PARAMETER, + OCD_ID_PARAMETER, + OCD_MUNICIPALITY_PARAMETER, + ORGANIZATION_PARAMETER, + ORIGIN_ID_PARAMETER, + PROVIDER_TYPE_NOT_PARAMETER, + PROVIDER_TYPE_PARAMETER, + STREET_PARAMETER, +) from services.utils import check_valid_concrete_field from services.utils.geocode_address import geocode_address @@ -533,24 +556,7 @@ class Meta: exclude = ["unit", "id"] -@extend_schema( - parameters=[ - OpenApiParameter( - name="id", - location=OpenApiParameter.QUERY, - description="Filter by ID or list of IDs.", - required=False, - type=str, - ), - OpenApiParameter( - name="ancestor", - location=OpenApiParameter.QUERY, - description="Filter by ancestor ID.", - required=False, - type=str, - ), - ] -) +@extend_schema(parameters=[ID_PARAMETER, ANCESTOR_ID_PARAMETER]) class ServiceNodeViewSet(JSONAPIViewSet, viewsets.ReadOnlyModelViewSet): queryset = ServiceNode.objects.all() serializer_class = ServiceNodeSerializer @@ -578,17 +584,7 @@ def get_queryset(self): register_view(ServiceNodeViewSet, "service_node") -@extend_schema( - parameters=[ - OpenApiParameter( - name="id", - location=OpenApiParameter.QUERY, - description="Filter by ID or list of IDs.", - required=False, - type=str, - ), - ] -) +@extend_schema(parameters=[ID_PARAMETER]) class ServiceViewSet(JSONAPIViewSet, viewsets.ReadOnlyModelViewSet): queryset = Service.objects.all() serializer_class = ServiceSerializer @@ -844,55 +840,13 @@ def render(self, data, media_type=None, renderer_context=None): @extend_schema( parameters=[ - OpenApiParameter( - name="id", - location=OpenApiParameter.QUERY, - description="Filter by ID or list of IDs.", - required=False, - type=str, - ), - OpenApiParameter( - name="municipality", - location=OpenApiParameter.QUERY, - description="Filter by municipality name or OCD ID.", - required=False, - type=str, - ), - OpenApiParameter( - name="organization", - location=OpenApiParameter.QUERY, - description="Filter by organization UUID.", - required=False, - type=str, - ), - OpenApiParameter( - name="city_as_department", - location=OpenApiParameter.QUERY, - description="Filter by city UUID.", - required=False, - type=str, - ), - OpenApiParameter( - name="provider_type", - location=OpenApiParameter.QUERY, - description="Filter by provider type numeric value.", - required=False, - type=int, - ), - OpenApiParameter( - name="provider_type__not", - location=OpenApiParameter.QUERY, - description="Exclude by provider type numeric value.", - required=False, - type=int, - ), - OpenApiParameter( - name="level", - location=OpenApiParameter.QUERY, - description="Filter by level.", - required=False, - type=str, - ), + ID_PARAMETER, + OCD_MUNICIPALITY_PARAMETER, + ORGANIZATION_PARAMETER, + CITY_AS_DEPARTMENT_PARAMETER, + PROVIDER_TYPE_PARAMETER, + PROVIDER_TYPE_NOT_PARAMETER, + LEVEL_PARAMETER, ] ) class UnitViewSet( @@ -1262,71 +1216,15 @@ def to_representation(self, obj): @extend_schema( parameters=[ - OpenApiParameter( - name="type", - location=OpenApiParameter.QUERY, - description="Filter by administrative division type or type ID.", - required=False, - type=str, - ), - OpenApiParameter( - name="lat", - location=OpenApiParameter.QUERY, - description="Filter by location. Give latitude in WGS84 system. If this parameter is given also the 'lon' " - "parameter is required.", - required=False, - type=float, - ), - OpenApiParameter( - name="lon", - location=OpenApiParameter.QUERY, - description="Filter by location. Give longitude in WGS84 system. If this parameter is given also the 'lat' " - "parameter is required.", - required=False, - type=float, - ), - OpenApiParameter( - name="input", - location=OpenApiParameter.QUERY, - description="Filter by partial match of name.", - required=False, - type=str, - ), - OpenApiParameter( - name="ocd_id", - location=OpenApiParameter.QUERY, - description="Filter by OCD ID.", - required=False, - type=str, - ), - OpenApiParameter( - name="geometry", - location=OpenApiParameter.QUERY, - description="Display administrative division boundary.", - required=False, - type=bool, - ), - OpenApiParameter( - name="origin_id", - location=OpenApiParameter.QUERY, - description="Filter by origin ID.", - required=False, - type=str, - ), - OpenApiParameter( - name="municipality", - location=OpenApiParameter.QUERY, - description="Filter by municipality.", - required=False, - type=str, - ), - OpenApiParameter( - name="date", - location=OpenApiParameter.QUERY, - description="Filter divisions based on their validity date. Format: YYYY-MM-DD.", - required=False, - type=str, - ), + DIVISION_TYPE_PARAMETER, + LATITUDE_PARAMETER, + LONGITUDE_PARAMETER, + INPUT_PARAMETER, + OCD_ID_PARAMETER, + GEOMETRY_PARAMETER, + ORIGIN_ID_PARAMETER, + MUNICIPALITY_PARAMETER, + DATE_PARAMETER, ] ) class AdministrativeDivisionViewSet(munigeo_api.AdministrativeDivisionViewSet): @@ -1356,59 +1254,13 @@ def get_queryset(self): @extend_schema( parameters=[ - OpenApiParameter( - name="street", - location=OpenApiParameter.QUERY, - description="Filter by street name.", - required=False, - type=str, - ), - OpenApiParameter( - name="municipality", - location=OpenApiParameter.QUERY, - description="Filter by municipality name or OCD ID.", - required=False, - type=str, - ), - OpenApiParameter( - name="number", - location=OpenApiParameter.QUERY, - description="Filter by building number.", - required=False, - type=str, - ), - OpenApiParameter( - name="lat", - location=OpenApiParameter.QUERY, - description="Filter by location. Give latitude in WGS84 system. If this parameter is given also the 'lon' " - "parameter is required.", - required=False, - type=float, - ), - OpenApiParameter( - name="lon", - location=OpenApiParameter.QUERY, - description="Filter by location. Give longitude in WGS84 system. If this parameter is given also the 'lat' " - "parameter is required.", - required=False, - type=float, - ), - OpenApiParameter( - name="distance", - location=OpenApiParameter.QUERY, - description="The maximum distance from the provided location, defined by the lat and lon parameters. " - "If this parameter is given also the 'lat' and 'lon' parameters are required.", - required=False, - type=float, - ), - OpenApiParameter( - name="bbox", - location=OpenApiParameter.QUERY, - description="Bounding box in the format 'left,bottom,right,top'. " - "Values must be floating points or integers.", - required=False, - type=str, - ), + STREET_PARAMETER, + OCD_MUNICIPALITY_PARAMETER, + BUILDING_NUMBER_PARAMETER, + LATITUDE_PARAMETER, + LONGITUDE_PARAMETER, + DISTANCE_PARAMETER, + BBOX_PARAMETER, ], ) class AddressViewSet(munigeo_api.AddressViewSet): diff --git a/services/open_api_parameters.py b/services/open_api_parameters.py new file mode 100644 index 00000000..008b27d4 --- /dev/null +++ b/services/open_api_parameters.py @@ -0,0 +1,174 @@ +from drf_spectacular.utils import OpenApiParameter + +ANCESTOR_ID_PARAMETER = OpenApiParameter( + name="ancestor", + location=OpenApiParameter.QUERY, + description="Filter by ancestor ID.", + required=False, + type=str, +) + +BBOX_PARAMETER = OpenApiParameter( + name="bbox", + location=OpenApiParameter.QUERY, + description="Bounding box in the format 'left,bottom,right,top'. Values must be floating points or integers.", + required=False, + type=str, +) + +BUILDING_NUMBER_PARAMETER = OpenApiParameter( + name="number", + location=OpenApiParameter.QUERY, + description="Filter by building number.", + required=False, + type=str, +) + +CITY_AS_DEPARTMENT_PARAMETER = OpenApiParameter( + name="city_as_department", + location=OpenApiParameter.QUERY, + description="Filter by city UUID.", + required=False, + type=str, +) + +DATE_PARAMETER = ( + OpenApiParameter( + name="date", + location=OpenApiParameter.QUERY, + description="Filter divisions based on their validity date. Format: YYYY-MM-DD.", + required=False, + type=str, + ), +) + +DISTANCE_PARAMETER = OpenApiParameter( + name="distance", + location=OpenApiParameter.QUERY, + description="The maximum distance from the provided location, defined by the lat and lon parameters. If this" + " parameter is given also the 'lat' and 'lon' parameters are required.", + required=False, + type=float, +) + +DIVISION_TYPE_PARAMETER = OpenApiParameter( + name="type", + location=OpenApiParameter.QUERY, + description="Filter by administrative division type or type ID.", + required=False, + type=str, +) + +GEOMETRY_PARAMETER = OpenApiParameter( + name="geometry", + location=OpenApiParameter.QUERY, + description="Display administrative division boundary.", + required=False, + type=bool, +) + +ID_PARAMETER = OpenApiParameter( + name="id", + location=OpenApiParameter.QUERY, + description="Filter by ID or list of IDs.", + required=False, + type=str, +) + +INPUT_PARAMETER = OpenApiParameter( + name="input", + location=OpenApiParameter.QUERY, + description="Filter by partial match of name.", + required=False, + type=str, +) + +LATITUDE_PARAMETER = OpenApiParameter( + name="lat", + location=OpenApiParameter.QUERY, + description="Filter by location. Give latitude in WGS84 system. If this parameter is given also the 'lon' " + "parameter is required.", + required=False, + type=float, +) + +LEVEL_PARAMETER = OpenApiParameter( + name="level", + location=OpenApiParameter.QUERY, + description="Filter by level.", + required=False, + type=str, +) + +LONGITUDE_PARAMETER = OpenApiParameter( + name="lon", + location=OpenApiParameter.QUERY, + description="Filter by location. Give longitude in WGS84 system. If this parameter is given also the 'lat' " + "parameter is required.", + required=False, + type=float, +) + +MUNICIPALITY_PARAMETER = OpenApiParameter( + name="municipality", + location=OpenApiParameter.QUERY, + description="Filter by municipality.", + required=False, + type=str, +) + +OCD_ID_PARAMETER = OpenApiParameter( + name="ocd_id", + location=OpenApiParameter.QUERY, + description="Filter by OCD ID.", + required=False, + type=str, +) + +OCD_MUNICIPALITY_PARAMETER = OpenApiParameter( + name="municipality", + location=OpenApiParameter.QUERY, + description="Filter by municipality name or OCD ID.", + required=False, + type=str, +) + +ORGANIZATION_PARAMETER = OpenApiParameter( + name="organization", + location=OpenApiParameter.QUERY, + description="Filter by organization UUID.", + required=False, + type=str, +) + +ORIGIN_ID_PARAMETER = OpenApiParameter( + name="origin_id", + location=OpenApiParameter.QUERY, + description="Filter by origin ID.", + required=False, + type=str, +) + +PROVIDER_TYPE_NOT_PARAMETER = OpenApiParameter( + name="provider_type__not", + location=OpenApiParameter.QUERY, + description="Exclude by provider type numeric value.", + required=False, + type=int, +) + +PROVIDER_TYPE_PARAMETER = OpenApiParameter( + name="provider_type", + location=OpenApiParameter.QUERY, + description="Filter by provider type numeric value.", + required=False, + type=int, +) + +STREET_PARAMETER = OpenApiParameter( + name="street", + location=OpenApiParameter.QUERY, + description="Filter by street name.", + required=False, + type=str, +) From 37e36afd5f6b27ebbc693cdd395fc0a2e25dcd50 Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Tue, 2 Jul 2024 13:52:34 +0300 Subject: [PATCH 7/8] Add services endpoints to DOC_ENDPOINTS --- smbackend/settings.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/smbackend/settings.py b/smbackend/settings.py index 14ada4f3..3fa06f3c 100644 --- a/smbackend/settings.py +++ b/smbackend/settings.py @@ -358,6 +358,11 @@ def gettext(s): "/exceptional_situations/api/v1/situation/", "/exceptional_situations/api/v1/situation_type/", "/api/v2/search", + "/api/v2/address/", + "/api/v2/administrative_division/", + "/api/v2/service_node/", + "/api/v2/service/", + "/api/v2/unit/", ] From ee8415b9d8cb001ffe194c23e25b72af407d889e Mon Sep 17 00:00:00 2001 From: juuso-j <68938778+juuso-j@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:22:21 +0300 Subject: [PATCH 8/8] Fix translated fields in OpenAPI docs --- services/api.py | 53 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/services/api.py b/services/api.py index e0785557..49303bde 100644 --- a/services/api.py +++ b/services/api.py @@ -15,7 +15,11 @@ from django.utils import timezone, translation from django.utils.module_loading import import_string from django_filters.rest_framework import DjangoFilterBackend -from drf_spectacular.utils import extend_schema +from drf_spectacular.utils import ( + extend_schema, + extend_schema_field, + extend_schema_serializer, +) from modeltranslation.translator import NotRegistered, translator from mptt.utils import drilldown_tree_for_node from munigeo import api as munigeo_api @@ -92,6 +96,17 @@ def register_view(klass, name, basename=None): logger = logging.getLogger(__name__) +class TranslationsSerializer(serializers.Serializer): + fi = serializers.CharField(required=False) + sv = serializers.CharField(required=False) + en = serializers.CharField(required=False) + + +@extend_schema_field(TranslationsSerializer) +class TranslationsField(serializers.CharField): + pass + + class MPTTModelSerializer(serializers.ModelSerializer): def __init__(self, *args, **kwargs): super(MPTTModelSerializer, self).__init__(*args, **kwargs) @@ -210,6 +225,13 @@ def to_representation(self, obj): return ret +class ServicesTranslatedModelSerializer(TranslatedModelSerializer): + def __init__(self, *args, **kwargs): + super(ServicesTranslatedModelSerializer, self).__init__(*args, **kwargs) + for field_name in self.translated_fields: + self.fields[field_name] = TranslationsField() + + def root_services(services): tree_ids = set(s.tree_id for s in services) return map( @@ -274,7 +296,7 @@ def to_representation(self, obj): class DepartmentSerializer( - TranslatedModelSerializer, MPTTModelSerializer, JSONAPISerializer + ServicesTranslatedModelSerializer, MPTTModelSerializer, JSONAPISerializer ): id = serializers.SerializerMethodField("get_uuid") parent = serializers.SerializerMethodField() @@ -296,7 +318,7 @@ def get_parent(self, obj): class ServiceNodeSerializer( - TranslatedModelSerializer, MPTTModelSerializer, JSONAPISerializer + ServicesTranslatedModelSerializer, MPTTModelSerializer, JSONAPISerializer ): children = serializers.PrimaryKeyRelatedField(many=True, read_only=True) @@ -350,7 +372,7 @@ class Meta: ) -class ServiceSerializer(TranslatedModelSerializer, JSONAPISerializer): +class ServiceSerializer(ServicesTranslatedModelSerializer, JSONAPISerializer): def to_representation(self, obj): ret = super(ServiceSerializer, self).to_representation(obj) ret["unit_count"] = {"municipality": {}} @@ -392,7 +414,7 @@ class Meta: fields = ["name", "root_service_node"] -class ServiceDetailsSerializer(TranslatedModelSerializer, JSONAPISerializer): +class ServiceDetailsSerializer(ServicesTranslatedModelSerializer, JSONAPISerializer): def to_representation(self, obj): ret = super(ServiceDetailsSerializer, self).to_representation(obj) service_data = RelatedServiceSerializer(obj.service).data @@ -496,7 +518,9 @@ def choicefield_string(choices, key, obj): return None -class UnitConnectionSerializer(TranslatedModelSerializer, serializers.ModelSerializer): +class UnitConnectionSerializer( + ServicesTranslatedModelSerializer, serializers.ModelSerializer +): section_type = serializers.SerializerMethodField() class Meta: @@ -515,7 +539,9 @@ class UnitConnectionViewSet(viewsets.ReadOnlyModelViewSet): register_view(UnitConnectionViewSet, "unit_connection") -class UnitEntranceSerializer(TranslatedModelSerializer, munigeo_api.GeoModelSerializer): +class UnitEntranceSerializer( + ServicesTranslatedModelSerializer, munigeo_api.GeoModelSerializer +): location = serializers.SerializerMethodField() class Meta: @@ -526,7 +552,11 @@ def get_location(self, obj): return munigeo_api.geom_to_json(obj.location, self.srs) -class UnitEntranceViewSet(munigeo_api.GeoModelAPIView, viewsets.ReadOnlyModelViewSet): +class UnitEntranceViewSet( + ServicesTranslatedModelSerializer, + munigeo_api.GeoModelAPIView, + viewsets.ReadOnlyModelViewSet, +): queryset = UnitEntrance.objects.all() serializer_class = UnitEntranceSerializer @@ -613,7 +643,7 @@ def get_queryset(self): class UnitSerializer( - TranslatedModelSerializer, munigeo_api.GeoModelSerializer, JSONAPISerializer + ServicesTranslatedModelSerializer, munigeo_api.GeoModelSerializer, JSONAPISerializer ): connections = UnitConnectionSerializer(many=True) entrances = UnitEntranceSerializer(many=True) @@ -1170,6 +1200,7 @@ def list(self, request, *args, **kwargs): ) +@extend_schema_serializer(deprecate_fields=["service_point_id"]) class AdministrativeDivisionSerializer(munigeo_api.AdministrativeDivisionSerializer): def to_representation(self, obj): ret = super(AdministrativeDivisionSerializer, self).to_representation(obj) @@ -1277,7 +1308,7 @@ class PostalCodeAreaViewSet(munigeo_api.PostalCodeAreaViewSet): register_view(PostalCodeAreaViewSet, "postalcodearea") -class AnnouncementSerializer(TranslatedModelSerializer, JSONAPISerializer): +class AnnouncementSerializer(ServicesTranslatedModelSerializer, JSONAPISerializer): class Meta: model = Announcement exclude = ["id", "active"] @@ -1291,7 +1322,7 @@ class AnnouncementViewSet(viewsets.ReadOnlyModelViewSet): register_view(AnnouncementViewSet, "announcement") -class ErrorMessageSerializer(TranslatedModelSerializer, JSONAPISerializer): +class ErrorMessageSerializer(ServicesTranslatedModelSerializer, JSONAPISerializer): class Meta: model = ErrorMessage exclude = ["id", "active"]