"""Location app views.""" from django.contrib.postgres.fields.jsonb import KeyTextTransform from django.db.models.deletion import ProtectedError from rest_framework import generics, status from rest_framework.response import Response from rest_framework.views import APIView from location import filters from location import models, serializers from location.filters import RegionFilter from location.views import common from utils.methods import get_permission_classes from utils.models import get_current_locale from utils.permissions import ( IsGuest, IsEstablishmentManager, IsEstablishmentAdministrator ) # Address class AddressListCreateView(common.AddressViewMixin, generics.ListCreateAPIView): """ ## List/Create view ### *GET* #### Description Get paginated list of addresses ##### Response E.g.: ``` { "count": 58, "next": 2, "previous": null, "results": [ { "id": 1, ... } ] } ``` ### *POST* #### Description Create a new address ##### Request Required * latitude (`float`) - latitude * longitude (`float`) - longitude * city_id (`int`) - identifier of city Available * district_name (`str`) - city district name * street_name_1 (`str`) - street name * street_name_2 (`str`) - street name (additional) * number (`int`) - city name * postal_code (`str`) - city postal code ##### Response E.g.: ``` { "id": 1, ... } ``` """ serializer_class = serializers.AddressDetailSerializer queryset = models.Address.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) class AddressRUDView(common.AddressViewMixin, generics.RetrieveUpdateDestroyAPIView): """ ## Retrieve/Update/Destroy view ### *GET* #### Description Return serialized object of an address by an identifier. ##### Response E.g.: ``` { "id": 1, ... } ``` ### *PUT*/*PATCH* #### Description Completely/Partially update an address object by an identifier. ##### Request Available * latitude (`float`) - latitude * longitude (`float`) - longitude * city_id (`int`) - identifier of city * district_name (`str`) - city district name * street_name_1 (`str`) - street name * street_name_2 (`str`) - street name (additional) * number (`int`) - city name * postal_code (`str`) - city postal code ##### Response E.g. ``` { "id": 1, ... } ``` ### *DELETE* #### Description Delete an address object by an identifier. ##### Response ``` No content ``` """ serializer_class = serializers.AddressDetailSerializer queryset = models.Address.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) # City class CityListCreateView(common.CityViewMixin, generics.ListCreateAPIView): """ ## List/Create view ### *GET* #### Description Return paginated list of cities ordered by a locale and filtered by a country code. Available filters: * search (`str`) - search city by name * country_code (`str`) - search city by its country code ##### Response E.g.: ``` { "count": 58, "next": 2, "previous": null, "results": [ { "id": 1, ... } ] } ``` ### *POST* #### Description Create a new city object. ##### Request Required * region_id (`int`) - region identifier * country_id (`int`) - country identifier Non-required: * image_id (`int`) - image identifier * name (`str`) - city name * postal_code (`str`) - city postal code * is_island (`boolean`) - flag that responds for is an island is this city ##### Response E.g.: ``` { "id": 1, ... } ``` """ serializer_class = serializers.CityBaseSerializer filter_class = filters.CityBackFilter permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) def get_queryset(self): """Overridden method 'get_queryset'.""" qs = models.City.objects.all().annotate(locale_name=KeyTextTransform(get_current_locale(), 'name'))\ .order_by('-modified').with_base_related() if self.request.country_code and self.request.query_params.get('country_code') is None: qs = qs.by_country_code(self.request.country_code) return qs class CityListSearchView(CityListCreateView): """ ## List/Create view ### *GET* #### Description Return list of cities **without pagination**, ordered by a locale and filtered by a country code. Available filters: * search (`str`) - search city by name * country_code (`str`) - search city by its country code ##### Response E.g.: ``` { "count": 58, "next": 2, "previous": null, "results": [ { "id": 1, ... } ] } ``` ### *POST* #### Description Create a new city object. ##### Request Required * region_id (`int`) - region identifier * country_id (`int`) - country identifier Non-required: * image_id (`int`) - image identifier * name (`str`) - city name * postal_code (`str`) - city postal code * is_island (`boolean`) - flag that responds for is an island is this city ##### Response E.g.: ``` { "id": 1, ... } ``` """ pagination_class = None def get_queryset(self): """An overridden get_queryset method.""" return ( models.City.objects. annotate(locale_name=KeyTextTransform(get_current_locale(), 'name')). order_by('locale_name') ) class CityRUDView(common.CityViewMixin, generics.RetrieveUpdateDestroyAPIView): """ ## Retrieve/Update/Destroy view ### *GET* #### Description Retrieve serialized instance of city object by an identifier ##### Response E.g.: ``` { "id": 1, ... } ``` ### *PUT*/*PATCH* #### Description Completely/Partially update a city object by an identifier. ##### Request Available: * region_id (`int`) - region identifier * country_id (`int`) - country identifier * image_id (`int`) - image identifier * name (`str`) - city name * postal_code (`str`) - city postal code * is_island (`boolean`) - flag that responds for is an island is this city ##### Response E.g.: ``` { "id": 1, ... } ``` ### *DELETE* #### Description Delete an instance of city by identifier ##### Response E.g.: ``` { "id": 1, ... } ``` """ serializer_class = serializers.CityDetailSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) def delete(self, request, *args, **kwargs): try: return self.destroy(request, *args, **kwargs) except ProtectedError: from rest_framework.serializers import ValidationError raise ValidationError({'detail': 'City couldn’t be deleted. Some objects has this city'}) # Region class RegionListCreateView(common.RegionViewMixin, generics.ListCreateAPIView): """ ## List/Create view ### *GET* #### Description Return non-paginated list of regions. Available filters: * country_id (`int`) - filter by a country identifier * sub_regions_by_region_id (`int`) - filter sub regions by region identifier * without_parent_region (`boolean`) - flag that responds for returning regions with/without parent region ##### Responds E.g.: ``` [ { "id": 1, ... } ] ``` ### *POST* #### Description Create new region/sub region ##### Request Available: * name (`str`) - (sub)region name * code (`str`) - (sub)region code * country_id (`int`) - identifier of `country` * parent_region_id (`int`) - identifier of `parent region` ##### Response E.g.: ``` { "id": 1, ... } ``` """ pagination_class = None serializer_class = serializers.RegionSerializer # ordering_fields = 'name' filter_class = RegionFilter permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) class RegionRUDView(common.RegionViewMixin, generics.RetrieveUpdateDestroyAPIView): """ ## Retrieve/Update/Destroy view ### *GET* #### Description Return serialized object of (sub)region by an identifier. ##### Responds E.g.: ``` [ { "id": 1, ... } ] ``` ### *PATCH*/*PUT* #### Description Completely/Partially update a (sub)region object by an identifier. ##### Request Available: * name (`str`) - (sub)region name * code (`str`) - (sub)region code * country_id (`int`) - identifier of `country` * parent_region_id (`int`) - identifier of `parent region` ##### Response E.g.: ``` { "id": 1, ... } ``` ### *DELETE* #### Description Delete an instance of (sub)region ##### Response E.g.: ``` No content ``` """ serializer_class = serializers.RegionSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) # Country class CountryBaseViewMixin: """Mixin for Country views.""" queryset = models.Country.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) class CountryListCreateView(CountryBaseViewMixin, generics.ListCreateAPIView): """ ## List/Create view. ### *GET* #### Description Return non-paginated list of countries ordered by a locale. ##### Response E.g.: ``` [ { "id": 1, ... } ] ``` ### *POST* #### Description Create new city ##### Request * code (`str`) - country code * svg_image (`file`) - svg icon of country flag * name (`JSON`) - country name, like - `{"en-GB": "text", "ru-RU": Text}` ##### Response E.g.: ``` { "id": 1, ... } ``` """ queryset = (models.Country.objects.annotate( locale_name=KeyTextTransform(get_current_locale(), 'name')).order_by('locale_name')) serializer_class = serializers.CountryBackSerializer pagination_class = None class CountryRUDView(CountryBaseViewMixin, generics.RetrieveUpdateDestroyAPIView): """ ## Retrieve/Update/Destroy view. ### *GET* #### Description Retrieve serialized object of country by identifier ##### Response E.g.: ``` { "id": 1, ... } ``` ### *PUT*/*PATCH* #### Description Completely/Partially update an address object by an identifier. ##### Request Available: * code (`str`) - country code * svg_image (`file`) - svg icon of country flag * name (`str`) - country name ##### Response E.g.: ``` { "id": 1, ... } ``` ### *DELETE* #### Description Delete a country object by an identifier. ##### Response E.g.: ``` No content ``` """ serializer_class = serializers.CountryBackSerializer class CountryCallingCodeListView(APIView): """ ## Country codes view. ### Response ``` [ "+7", "+386", "+352" ] ``` ### Description Return an array of unique country code for all countries in a database. """ pagination_class = None permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, IsGuest, ) def get(self, request, *args, **kwargs): """ ## Country codes view. ### Response ``` [ "+7", "+386", "+352" ] ``` ### Description Return an array of unique country code for all countries in a database. """ return Response(data=models.Country.objects.aggregate_country_codes(), status=status.HTTP_200_OK)