gault-millau/apps/location/views/back.py
2020-02-10 14:50:37 +03:00

538 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""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 couldnt 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)