Refactor some establishment serializer

This commit is contained in:
evgeniy-st 2019-09-25 15:32:45 +03:00
parent 1534c9b09c
commit f18c18110c
7 changed files with 112 additions and 83 deletions

View File

@ -13,8 +13,9 @@ from phonenumber_field.modelfields import PhoneNumberField
from location.models import Address from location.models import Address
from collection.models import Collection from collection.models import Collection
from main.models import MetaDataContent
from review.models import Review from review.models import Review
from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField, URLImageMixin, from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
TranslatedFieldsMixin, BaseAttributes) TranslatedFieldsMixin, BaseAttributes)
@ -70,6 +71,20 @@ class EstablishmentSubType(ProjectBaseMixin, TranslatedFieldsMixin):
class EstablishmentQuerySet(models.QuerySet): class EstablishmentQuerySet(models.QuerySet):
"""Extended queryset for Establishment model.""" """Extended queryset for Establishment model."""
def with_base_related(self):
"""Return qs with related objects."""
return self.select_related('address').prefetch_related(
models.Prefetch('tags',
MetaDataContent.objects.select_related(
'metadata__category'))
)
def with_extended_related(self):
return self.select_related('establishment_type').\
prefetch_related('establishment_subtypes', 'awards', 'schedule',
'phones').\
prefetch_actual_employees()
def search(self, value, locale=None): def search(self, value, locale=None):
"""Search text in JSON fields.""" """Search text in JSON fields."""
if locale is not None: if locale is not None:
@ -312,12 +327,12 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
return country.low_price, country.high_price return country.low_price, country.high_price
# todo: make via prefetch # todo: make via prefetch
@property # @property
def subtypes(self): # def subtypes(self):
return EstablishmentSubType.objects.filter( # return EstablishmentSubType.objects.filter(
subtype_establishment=self, # subtype_establishment=self,
establishment_type=self.establishment_type, # establishment_type=self.establishment_type,
establishment_type__use_subtypes=True) # establishment_type__use_subtypes=True)
def set_establishment_type(self, establishment_type): def set_establishment_type(self, establishment_type):
self.establishment_type = establishment_type self.establishment_type = establishment_type

View File

@ -1,12 +1,9 @@
import json
from rest_framework import serializers from rest_framework import serializers
from establishment import models from establishment import models
from timetable.models import Timetable
from establishment.serializers import ( from establishment.serializers import (
EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer, EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer,
ContactPhonesSerializer, SocialNetworkRelatedSerializers, EstablishmentDetailSerializer ContactPhonesSerializer, SocialNetworkRelatedSerializers,
) EstablishmentTypeSerializer)
from main.models import Currency from main.models import Currency
@ -21,6 +18,7 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
emails = ContactEmailsSerializer(read_only=True, many=True, ) emails = ContactEmailsSerializer(read_only=True, many=True, )
socials = SocialNetworkRelatedSerializers(read_only=True, many=True, ) socials = SocialNetworkRelatedSerializers(read_only=True, many=True, )
slug = serializers.SlugField(required=True, allow_blank=False, max_length=50) slug = serializers.SlugField(required=True, allow_blank=False, max_length=50)
type = EstablishmentTypeSerializer(source='establishment_type')
class Meta: class Meta:
model = models.Establishment model = models.Establishment
@ -52,6 +50,7 @@ class EstablishmentRUDSerializer(EstablishmentBaseSerializer):
phones = ContactPhonesSerializer(read_only=False, many=True, ) phones = ContactPhonesSerializer(read_only=False, many=True, )
emails = ContactEmailsSerializer(read_only=False, many=True, ) emails = ContactEmailsSerializer(read_only=False, many=True, )
socials = SocialNetworkRelatedSerializers(read_only=False, many=True, ) socials = SocialNetworkRelatedSerializers(read_only=False, many=True, )
type = EstablishmentTypeSerializer(source='establishment_type')
class Meta: class Meta:
model = models.Establishment model = models.Establishment

View File

@ -1,17 +1,17 @@
"""Establishment serializers.""" """Establishment serializers."""
from rest_framework import serializers from rest_framework import serializers
from django.utils.translation import gettext_lazy as _
from comment import models as comment_models from comment import models as comment_models
from comment.serializers import common as comment_serializers from comment.serializers import common as comment_serializers
from establishment import models from establishment import models
from favorites.models import Favorites from favorites.models import Favorites
from location.serializers import AddressSerializer from location.serializers import AddressSimpleSerializer
from main.models import MetaDataContent from main.models import MetaDataContent
from main.serializers import MetaDataContentSerializer, AwardSerializer, CurrencySerializer from main.serializers import MetaDataContentSerializer, AwardSerializer, CurrencySerializer
from review import models as review_models from review import models as review_models
from timetable.serialziers import ScheduleRUDSerializer from timetable.serialziers import ScheduleRUDSerializer
from utils import exceptions as utils_exceptions from utils import exceptions as utils_exceptions
from django.utils.translation import gettext_lazy as _ from utils.serializers import TranslatedField
class ContactPhonesSerializer(serializers.ModelSerializer): class ContactPhonesSerializer(serializers.ModelSerializer):
@ -142,11 +142,11 @@ class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
class EstablishmentBaseSerializer(serializers.ModelSerializer): class EstablishmentBaseSerializer(serializers.ModelSerializer):
"""Base serializer for Establishment model.""" """Base serializer for Establishment model."""
type = EstablishmentTypeSerializer(source='establishment_type', read_only=True)
subtypes = EstablishmentSubTypeSerializer(many=True) preview_image = serializers.URLField(source='preview_image_url')
address = AddressSerializer()
tags = MetaDataContentSerializer(many=True)
slug = serializers.SlugField(allow_blank=False, required=True, max_length=50) slug = serializers.SlugField(allow_blank=False, required=True, max_length=50)
address = AddressSimpleSerializer()
tags = MetaDataContentSerializer(many=True)
class Meta: class Meta:
"""Meta class.""" """Meta class."""
@ -159,60 +159,53 @@ class EstablishmentBaseSerializer(serializers.ModelSerializer):
'price_level', 'price_level',
'toque_number', 'toque_number',
'public_mark', 'public_mark',
'type', 'slug',
'subtypes', 'preview_image',
'in_favorites',
'address', 'address',
'tags', 'tags',
'slug',
] ]
class EstablishmentListSerializer(EstablishmentBaseSerializer): class EstablishmentListSerializer(EstablishmentBaseSerializer):
"""Serializer for Establishment model.""" """Serializer for Establishment model."""
# Annotated fields
in_favorites = serializers.BooleanField(allow_null=True) in_favorites = serializers.BooleanField(allow_null=True)
preview_image = serializers.URLField(source='preview_image_url') class Meta(EstablishmentBaseSerializer.Meta):
class Meta:
"""Meta class.""" """Meta class."""
model = models.Establishment
fields = EstablishmentBaseSerializer.Meta.fields + [ fields = EstablishmentBaseSerializer.Meta.fields + [
'in_favorites', 'in_favorites',
'preview_image',
] ]
class EstablishmentDetailSerializer(EstablishmentListSerializer): class EstablishmentDetailSerializer(EstablishmentListSerializer):
"""Serializer for Establishment model.""" """Serializer for Establishment model."""
description_translated = serializers.CharField(allow_null=True)
description_translated = TranslatedField()
image = serializers.URLField(source='image_url')
type = EstablishmentTypeSerializer(source='establishment_type', read_only=True)
subtypes = EstablishmentSubTypeSerializer(many=True, source='establishment_subtypes')
awards = AwardSerializer(many=True) awards = AwardSerializer(many=True)
schedule = ScheduleRUDSerializer(many=True, allow_null=True) schedule = ScheduleRUDSerializer(many=True, allow_null=True)
phones = ContactPhonesSerializer(read_only=True, many=True, ) phones = ContactPhonesSerializer(read_only=True, many=True)
emails = ContactEmailsSerializer(read_only=True, many=True, ) emails = ContactEmailsSerializer(read_only=True, many=True)
review = serializers.SerializerMethodField() review = serializers.SerializerMethodField()
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees', employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
many=True) many=True)
menu = MenuSerializers(source='menu_set', many=True, read_only=True) menu = MenuSerializers(source='menu_set', many=True, read_only=True)
best_price_menu = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True) best_price_menu = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
best_price_carte = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True) best_price_carte = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
slug = serializers.SlugField(required=True, allow_blank=False, max_length=50) class Meta(EstablishmentListSerializer.Meta):
in_favorites = serializers.SerializerMethodField()
image = serializers.URLField(source='image_url')
class Meta:
"""Meta class.""" """Meta class."""
model = models.Establishment
fields = EstablishmentListSerializer.Meta.fields + [ fields = EstablishmentListSerializer.Meta.fields + [
'description_translated', 'description_translated',
'price_level',
'image', 'image',
'subtypes',
'type',
'awards', 'awards',
'schedule', 'schedule',
'website', 'website',
@ -228,23 +221,23 @@ class EstablishmentDetailSerializer(EstablishmentListSerializer):
'best_price_menu', 'best_price_menu',
'best_price_carte', 'best_price_carte',
'transportation', 'transportation',
'slug',
] ]
# todo: refactor this s (make as prefetch to model as attr or make as model property)
def get_review(self, obj): def get_review(self, obj):
"""Serializer method for getting last published review""" """Serializer method for getting last published review"""
return ReviewSerializer(obj.reviews.by_status(status=review_models.Review.READY) return ReviewSerializer(obj.reviews.by_status(status=review_models.Review.READY)
.order_by('-published_at').first()).data .order_by('-published_at').first()).data
def get_in_favorites(self, obj): # def get_in_favorites(self, obj):
"""Get in_favorites status flag""" # """Get in_favorites status flag"""
user = self.context.get('request').user # user = self.context.get('request').user
if user.is_authenticated: # if user.is_authenticated:
return obj.id in user.favorites.by_content_type(app_label='establishment', # return obj.id in user.favorites.by_content_type(app_label='establishment',
model='establishment')\ # model='establishment')\
.values_list('object_id', flat=True) # .values_list('object_id', flat=True)
else: # else:
return False # return False
class EstablishmentCommentCreateSerializer(comment_serializers.CommentSerializer): class EstablishmentCommentCreateSerializer(comment_serializers.CommentSerializer):

View File

@ -4,10 +4,17 @@ from rest_framework import generics
from establishment import models from establishment import models
from establishment import serializers from establishment import serializers
from establishment.views.common import EstablishmentMixin
class EstablishmentListCreateView(EstablishmentMixin, generics.ListCreateAPIView): class EstablishmentMixinViews:
"""Establishment mixin."""
def get_queryset(self):
"""Overrided method 'get_queryset'."""
return models.Establishment.objects.published().with_related()
class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAPIView):
"""Establishment list/create view.""" """Establishment list/create view."""
queryset = models.Establishment.objects.all() queryset = models.Establishment.objects.all()
serializer_class = serializers.EstablishmentListCreateSerializer serializer_class = serializers.EstablishmentListCreateSerializer

View File

@ -1,16 +1 @@
"""Establishment app views.""" """Establishment app views."""
from rest_framework import permissions
from establishment import models
class EstablishmentMixin:
"""Establishment mixin."""
permission_classes = (permissions.AllowAny,)
def get_queryset(self):
"""Overrided method 'get_queryset'."""
return models.Establishment.objects.published() \
.prefetch_actual_employees()

View File

@ -1,27 +1,47 @@
"""Establishment app views.""" """Establishment app views."""
from django.contrib.gis.geos import Point from django.contrib.gis.geos import Point
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from rest_framework import generics, permissions from rest_framework import generics, permissions
from comment import models as comment_models from comment import models as comment_models
from establishment import filters from establishment import filters, models, serializers
from establishment import models, serializers
from establishment.views import EstablishmentMixin
from main.models import MetaDataContent from main.models import MetaDataContent
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
class EstablishmentListView(EstablishmentMixin, generics.ListAPIView): class EstablishmentMixinView:
"""Establishment mixin."""
permission_classes = (permissions.AllowAny,)
def get_queryset(self):
"""Overrided method 'get_queryset'."""
return models.Establishment.objects.published().with_base_related().\
annotate_in_favorites(self.request.user)
class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView):
"""Resource for getting a list of establishments.""" """Resource for getting a list of establishments."""
serializer_class = serializers.EstablishmentListSerializer
filter_class = filters.EstablishmentFilter filter_class = filters.EstablishmentFilter
serializer_class = serializers.EstablishmentListSerializer
def get_queryset(self): def get_queryset(self):
"""Overridden method 'get_queryset'.""" """Overridden method 'get_queryset'."""
qs = super(EstablishmentListView, self).get_queryset() qs = super(EstablishmentListView, self).get_queryset()
return qs.by_country_code(code=self.request.country_code) \ if self.request.country_code:
.annotate_in_favorites(user=self.request.user) qs = qs.by_country_code(self.request.country_code)
return qs
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
"""Resource for getting a establishment."""
lookup_field = 'slug'
serializer_class = serializers.EstablishmentDetailSerializer
def get_queryset(self):
return super().get_queryset().with_extended_related()
class EstablishmentSimilarListView(EstablishmentListView): class EstablishmentSimilarListView(EstablishmentListView):
@ -33,11 +53,6 @@ class EstablishmentSimilarListView(EstablishmentListView):
return super().get_queryset().similar(establishment_slug=self.kwargs.get('slug'))\ return super().get_queryset().similar(establishment_slug=self.kwargs.get('slug'))\
.order_by('-total_mark')[:13] .order_by('-total_mark')[:13]
class EstablishmentRetrieveView(EstablishmentMixin, generics.RetrieveAPIView):
"""Resource for getting a establishment."""
lookup_field = 'slug'
serializer_class = serializers.EstablishmentDetailSerializer
class EstablishmentTypeListView(generics.ListAPIView): class EstablishmentTypeListView(generics.ListAPIView):
"""Resource for getting a list of establishment types.""" """Resource for getting a list of establishment types."""

View File

@ -1,7 +1,6 @@
"""Location app common serializers.""" """Location app common serializers."""
from django.contrib.gis.geos import Point from django.contrib.gis.geos import Point
from rest_framework import serializers from rest_framework import serializers
from location import models from location import models
from utils.serializers import TranslatedField from utils.serializers import TranslatedField
@ -86,6 +85,7 @@ class CitySerializer(serializers.ModelSerializer):
class AddressSerializer(serializers.ModelSerializer): class AddressSerializer(serializers.ModelSerializer):
"""Address serializer.""" """Address serializer."""
city_id = serializers.PrimaryKeyRelatedField( city_id = serializers.PrimaryKeyRelatedField(
source='city', source='city',
queryset=models.City.objects.all()) queryset=models.City.objects.all())
@ -128,3 +128,18 @@ class AddressSerializer(serializers.ModelSerializer):
setattr(instance, 'geo_lon', float(0)) setattr(instance, 'geo_lon', float(0))
return super().to_representation(instance) return super().to_representation(instance)
class AddressSimpleSerializer(serializers.ModelSerializer):
"""Serializer for address obj in related objects."""
class Meta:
"""Meta class."""
model = models.Address
fields = (
'id',
'street_name_1',
'street_name_2',
'number',
'postal_code',
)