gault-millau/apps/collection/serializers/common.py
2020-02-05 14:16:36 +03:00

315 lines
12 KiB
Python

from django.shortcuts import get_object_or_404
from rest_framework import serializers
from rest_framework_recursive.fields import RecursiveField
from slugify import slugify
from collection import models
from establishment.serializers import EstablishmentGuideElementSerializer
from location import models as location_models
from main.serializers import SiteShortSerializer
from product.serializers import ProductGuideElementSerializer
from utils import exceptions
from utils.methods import string_random
from utils.serializers import TranslatedField
class CollectionBaseSerializer(serializers.ModelSerializer):
"""Collection base serializer"""
name_translated = TranslatedField()
description_translated = TranslatedField()
class Meta:
model = models.Collection
fields = [
'id',
'name_translated',
'description_translated',
'image_url',
'slug',
]
class CollectionSerializer(CollectionBaseSerializer):
"""Collection serializer"""
# COMMON
block_size = serializers.JSONField()
is_publish = serializers.BooleanField()
on_top = serializers.BooleanField()
slug = serializers.SlugField(allow_blank=False, required=True, max_length=50)
# REQUEST
start = serializers.DateTimeField(write_only=True)
end = serializers.DateTimeField(write_only=True)
country = serializers.PrimaryKeyRelatedField(
queryset=location_models.Country.objects.all(),
write_only=True)
class Meta(CollectionBaseSerializer.Meta):
fields = CollectionBaseSerializer.Meta.fields + [
'start',
'end',
'is_publish',
'on_top',
'country',
'block_size',
]
class GuideFilterBaseSerializer(serializers.ModelSerializer):
"""GuideFilter serializer"""
class Meta:
"""Meta class."""
model = models.GuideFilter
fields = [
'id',
'establishment_type_json',
'country_json',
'region_json',
'sub_region_json',
'wine_region_json',
'with_mark',
'locale_json',
'max_mark',
'min_mark',
'review_vintage_json',
'review_state_json',
'guide',
]
extra_kwargs = {
'guide': {'write_only': True, 'required': False},
'max_mark': {'required': True},
'min_mark': {'required': True},
}
@property
def request_kwargs(self):
"""Get url kwargs from request."""
return self.context.get('request').parser_context.get('kwargs')
def create(self, validated_data):
"""Overridden create method."""
guide = get_object_or_404(models.Guide.objects.all(),
pk=self.request_kwargs.get('pk'))
validated_data['guide'] = guide
guide_filter = super().create(validated_data)
guide.generate_elements()
return guide_filter
class GuideBaseSerializer(serializers.ModelSerializer):
"""Guide serializer"""
state_display = serializers.CharField(source='get_state_display',
read_only=True)
guide_type_display = serializers.CharField(read_only=True)
site_detail = SiteShortSerializer(read_only=True,
source='site')
guide_filters = GuideFilterBaseSerializer(read_only=True,
source='guidefilter')
# counters
# restaurant_counter = serializers.IntegerField(read_only=True)
# shop_counter = serializers.IntegerField(read_only=True)
# wine_counter = serializers.IntegerField(read_only=True)
# present_objects_counter = serializers.IntegerField(read_only=True)
count_objects_during_init = serializers.IntegerField(read_only=True,
source='count_related_objects')
class Meta:
model = models.Guide
fields = [
'id',
'name',
'start',
'end',
'vintage',
'slug',
'guide_type',
'guide_type_display',
'site',
'site_detail',
'state',
'state_display',
'guide_filters',
# 'restaurant_counter',
# 'shop_counter',
# 'wine_counter',
# 'present_objects_counter',
'count_objects_during_init',
]
extra_kwargs = {
'guide_type': {'write_only': True, 'required': True},
'site': {'write_only': True, 'required': True},
'state': {'write_only': True},
'start': {'required': True},
'slug': {'required': False},
'count_objects_during_init': {'read_only': True},
'vintage': {'required': True},
}
def create(self, validated_data):
"""Overridden create method."""
slug = validated_data.get('slug')
name = validated_data.get('name')
vintage = validated_data.get('vintage')
if not slug:
slug = slugify(f'{name} {vintage}', word_boundary=True)
while models.Guide.objects.filter(slug=slug).exists():
slug = slugify(f'{name} {vintage} {string_random()}', word_boundary=True)
validated_data['slug'] = slug
return super(GuideBaseSerializer, self).create(validated_data)
class GuideShortSerializer(serializers.ModelSerializer):
"""Serializer for model Guide."""
class Meta(GuideBaseSerializer.Meta):
"""Meta-class."""
fields = [
'id',
'name',
]
class GuideElementBaseSerializer(serializers.ModelSerializer):
"""Serializer for model GuideElement."""
establishment_detail = EstablishmentGuideElementSerializer(read_only=True,
source='establishment')
section_name = serializers.CharField(source='section.name',
allow_null=True)
wine_color_section_name = serializers.CharField(source='wine_color_section.name',
allow_null=True)
wine_region_name = serializers.CharField(source='wine_region.name',
allow_null=True)
node_name = serializers.CharField(source='guide_element_type.name')
label_photo = serializers.ImageField(source='label_photo.image', allow_null=True)
city_name = serializers.CharField(source='city.name', allow_null=True)
product_detail = ProductGuideElementSerializer(read_only=True, source='product')
children = RecursiveField(required=False, many=True, source='get_children')
class Meta:
"""Meta class."""
model = models.GuideElement
fields = [
'id',
'node_name',
'establishment_detail',
'review',
'product_detail',
'priority',
'city_name',
'section_name',
'wine_color_section_name',
'wine_region_name',
'children',
'label_photo',
]
class AdvertorialBaseSerializer(serializers.ModelSerializer):
"""Serializer for model Advertorial."""
class Meta:
"""Meta class."""
model = models.Advertorial
fields = [
'number_of_pages',
'right_pages',
'guide_element',
]
extra_kwargs = {
'guide_element': {'required': False}
}
@property
def request_kwargs(self):
return self.context.get('request').parser_context.get('kwargs')
def validate(self, attrs):
# check existence in guide
guide = get_object_or_404(models.Guide.objects.all(),
pk=self.request_kwargs.get('pk'))
root_node = models.GuideElement.objects.get_root_node(guide)
guide_element_qs = root_node.get_descendants().filter(pk=self.request_kwargs.get('element_pk'))
guide_element = guide_element_qs.first()
if not guide_element_qs.exists():
raise exceptions.GuideElementError()
if models.Advertorial.objects.filter(guide_element=guide_element).exists():
raise exceptions.AdvertorialError()
attrs['guide_element'] = guide_element
return attrs
class GuideElementExportSerializer(GuideElementBaseSerializer):
"""GuideElement export serializer."""
# ESTABLISHMENT
name = serializers.CharField(source='establishment.name', default=None)
public_mark = serializers.CharField(source='establishment.public_mark_display', default=None)
toque_number = serializers.IntegerField(source='establishment.toque_number', default=None)
schedule = serializers.DictField(source='establishment.schedule_display',
default=None)
address = serializers.CharField(source='establishment.address.full_address',
default=None)
phones = serializers.ListField(source='establishment.contact_phones',
default=None)
establishment_type = serializers.CharField(source='establishment.establishment_type.label',
default=None)
establishment_subtypes = serializers.ListField(source='establishment.establishment_subtype_labels',
default=None)
review = serializers.DictField(source='establishment.last_published_review_data',
default=None)
price_level = serializers.CharField(source='establishment.price_level_display',
default=None)
metadata = serializers.ListField(source='establishment.metadata',
default=None)
advertorial = serializers.DictField(source='advertorial.__dict__', default=None)
# PRODUCT
product_name = serializers.CharField(source='product.name',
default=None)
product_review = serializers.DictField(source='product.last_published_review_data',
default=None)
product_type = serializers.CharField(source='product.product_type.label',
default=None)
product_subtypes = serializers.CharField(source='product.product_subtype_labels',
default=None)
product_city = serializers.CharField(source='product.establishment.address.city.name',
default=None)
product_address = serializers.CharField(source='product.establishment.address.full_address',
default=None)
product_metadata = serializers.ListField(source='product.metadata',
default=None)
class Meta:
model = models.GuideElement
fields = [
'id',
'guide',
'node_name',
'city_name',
'wine_color_section_name',
'name',
'public_mark',
'toque_number',
'schedule',
'address',
'phones',
'establishment_type',
'establishment_subtypes',
'review',
'price_level',
'metadata',
'advertorial',
'product_name',
'product_review',
'product_type',
'product_subtypes',
'product_address',
'product_city',
'product_metadata',
]