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 collection.models import Collection
from main.models import MetaDataContent
from review.models import Review
from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField, URLImageMixin,
from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
TranslatedFieldsMixin, BaseAttributes)
@ -70,6 +71,20 @@ class EstablishmentSubType(ProjectBaseMixin, TranslatedFieldsMixin):
class EstablishmentQuerySet(models.QuerySet):
"""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):
"""Search text in JSON fields."""
if locale is not None:
@ -228,7 +243,7 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
name = models.CharField(_('name'), max_length=255, default='')
name_translated = models.CharField(_('Transliterated name'),
max_length=255, default='')
max_length=255, default='')
description = TJSONField(blank=True, null=True, default=None,
verbose_name=_('description'),
help_text='{"en-GB":"some text"}')
@ -312,12 +327,12 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
return country.low_price, country.high_price
# todo: make via prefetch
@property
def subtypes(self):
return EstablishmentSubType.objects.filter(
subtype_establishment=self,
establishment_type=self.establishment_type,
establishment_type__use_subtypes=True)
# @property
# def subtypes(self):
# return EstablishmentSubType.objects.filter(
# subtype_establishment=self,
# establishment_type=self.establishment_type,
# establishment_type__use_subtypes=True)
def set_establishment_type(self, establishment_type):
self.establishment_type = establishment_type

View File

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

View File

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

View File

@ -4,10 +4,17 @@ from rest_framework import generics
from establishment import models
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."""
queryset = models.Establishment.objects.all()
serializer_class = serializers.EstablishmentListCreateSerializer

View File

@ -1,16 +1 @@
"""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."""
from django.contrib.gis.geos import Point
from django.shortcuts import get_object_or_404
from rest_framework import generics, permissions
from comment import models as comment_models
from establishment import filters
from establishment import models, serializers
from establishment.views import EstablishmentMixin
from establishment import filters, models, serializers
from main.models import MetaDataContent
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."""
serializer_class = serializers.EstablishmentListSerializer
filter_class = filters.EstablishmentFilter
serializer_class = serializers.EstablishmentListSerializer
def get_queryset(self):
"""Overridden method 'get_queryset'."""
qs = super(EstablishmentListView, self).get_queryset()
return qs.by_country_code(code=self.request.country_code) \
.annotate_in_favorites(user=self.request.user)
if self.request.country_code:
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):
@ -33,11 +53,6 @@ class EstablishmentSimilarListView(EstablishmentListView):
return super().get_queryset().similar(establishment_slug=self.kwargs.get('slug'))\
.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):
"""Resource for getting a list of establishment types."""

View File

@ -1,7 +1,6 @@
"""Location app common serializers."""
from django.contrib.gis.geos import Point
from rest_framework import serializers
from location import models
from utils.serializers import TranslatedField
@ -86,6 +85,7 @@ class CitySerializer(serializers.ModelSerializer):
class AddressSerializer(serializers.ModelSerializer):
"""Address serializer."""
city_id = serializers.PrimaryKeyRelatedField(
source='city',
queryset=models.City.objects.all())
@ -128,3 +128,18 @@ class AddressSerializer(serializers.ModelSerializer):
setattr(instance, 'geo_lon', float(0))
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',
)