gault-millau/apps/news/serializers.py
2019-12-19 15:12:49 +03:00

394 lines
13 KiB
Python

"""News app common serializers."""
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework.fields import SerializerMethodField
from account.serializers.common import UserBaseSerializer
from gallery.models import Image
from main.models import SiteSettings, Carousel
from location import models as location_models
from location.serializers import CountrySimpleSerializer, AddressBaseSerializer
from news import models
from tag.serializers import TagBaseSerializer
from utils import exceptions as utils_exceptions
from utils.serializers import (TranslatedField, ProjectModelSerializer,
FavoritesCreateSerializer, ImageBaseSerializer, CarouselCreateSerializer)
from rating import models as rating_models
from django.shortcuts import get_object_or_404
from utils.models import get_current_locale, get_default_locale
class AgendaSerializer(ProjectModelSerializer):
event_datetime = serializers.DateTimeField()
address = AddressBaseSerializer()
content_translated = TranslatedField()
class Meta:
"""Meta class."""
model = models.Agenda
fields = (
'id',
'event_datetime',
'address',
'content_translated'
)
class NewsBannerSerializer(ProjectModelSerializer):
title_translated = TranslatedField()
image_url = serializers.URLField()
content_url = serializers.URLField()
class Meta:
"""Meta class."""
model = models.NewsBanner
fields = (
'id',
'title_translated',
'image_url',
'content_url'
)
class NewsTypeSerializer(serializers.ModelSerializer):
"""News type serializer."""
class Meta:
"""Meta class."""
model = models.NewsType
fields = ('id', 'name')
class NewsBaseSerializer(ProjectModelSerializer):
"""Base serializer for News model."""
title_translated = TranslatedField()
subtitle_translated = TranslatedField()
news_type = NewsTypeSerializer(read_only=True)
tags = TagBaseSerializer(read_only=True, many=True, source='visible_tags')
in_favorites = serializers.BooleanField(allow_null=True, read_only=True)
view_counter = serializers.IntegerField(read_only=True)
slug = serializers.SerializerMethodField(read_only=True, allow_null=True)
def get_slug(self, obj):
if obj.slugs:
return obj.slugs.get(get_current_locale()) \
or obj.slugs.get(get_default_locale()) \
or next(iter(obj.slugs.values()))
class Meta:
"""Meta class."""
model = models.News
fields = (
'id',
'slug',
'title_translated',
'subtitle_translated',
'is_highlighted',
'news_type',
'tags',
'view_counter',
)
class NewsSimilarListSerializer(NewsBaseSerializer):
"""List serializer for News model."""
preview_image_url = serializers.URLField()
class Meta(NewsBaseSerializer.Meta):
"""Meta class."""
fields = NewsBaseSerializer.Meta.fields + (
'preview_image_url',
)
class NewsListSerializer(NewsBaseSerializer):
"""List serializer for News model."""
image = ImageBaseSerializer(source='crop_main_image', allow_null=True)
class Meta(NewsBaseSerializer.Meta):
"""Meta class."""
fields = NewsBaseSerializer.Meta.fields + (
'image',
)
class NewsDetailSerializer(NewsBaseSerializer):
"""News detail serializer."""
description_translated = TranslatedField()
country = CountrySimpleSerializer(read_only=True)
author = UserBaseSerializer(source='created_by', read_only=True)
state_display = serializers.CharField(source='get_state_display',
read_only=True)
gallery = ImageBaseSerializer(read_only=True, source='crop_gallery', many=True)
start = serializers.DateTimeField(source='publication_datetime', read_only=True)
class Meta(NewsBaseSerializer.Meta):
"""Meta class."""
fields = NewsBaseSerializer.Meta.fields + (
'description_translated',
'start',
'end',
'is_publish',
'state',
'state_display',
'author',
'country',
'gallery',
)
class NewsDetailWebSerializer(NewsDetailSerializer):
"""News detail serializer for web users.."""
same_theme = SerializerMethodField()
should_read = SerializerMethodField()
agenda = AgendaSerializer()
banner = NewsBannerSerializer()
class Meta(NewsDetailSerializer.Meta):
"""Meta class."""
fields = NewsDetailSerializer.Meta.fields + (
'same_theme',
'should_read',
'agenda',
'banner',
)
def get_same_theme(self, obj):
return NewsSimilarListSerializer(obj.same_theme(self.context['request'].user), many=True, read_only=True).data
def get_should_read(self, obj):
return NewsSimilarListSerializer(obj.should_read(self.context['request'].user), many=True, read_only=True).data
class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
"""News back office base serializer."""
is_published = serializers.BooleanField(source='is_publish', read_only=True)
class Meta(NewsBaseSerializer.Meta):
"""Meta class."""
fields = NewsBaseSerializer.Meta.fields + (
'title',
'backoffice_title',
'subtitle',
'slugs',
'locale_to_description_is_active',
'is_published',
'duplication_date',
'must_of_the_week',
'publication_date',
'publication_time',
)
extra_kwargs = {
'duplication_date': {'read_only': True},
'locale_to_description_is_active': {'allow_null': False},
'must_of_the_week': {'allow_null': False},
}
def create(self, validated_data):
slugs = validated_data.get('slugs')
if slugs:
if models.News.objects.filter(
slugs__values__contains=list(slugs.values())
).exists():
raise serializers.ValidationError({'slugs': _('News with this slug already exists.')})
instance = super().create(validated_data)
Carousel.objects.create_or_destroy(instance, instance.country)
return instance
def update(self, instance, validated_data):
slugs = validated_data.get('slugs')
if slugs:
if models.News.objects.filter(
slugs__values__contains=list(slugs.values())
).exclude(pk=instance.pk).exists():
raise serializers.ValidationError({'slugs': _('News with this slug already exists.')})
ret = super().update(instance, validated_data)
if ret.must_of_the_week != instance.must_of_the_week:
Carousel.objects.create_or_destroy(instance, instance.address.city.country)
return ret
class NewsBackOfficeDuplicationInfoSerializer(serializers.ModelSerializer):
"""Duplication info for news detail."""
country = CountrySimpleSerializer(read_only=True)
class Meta:
model = models.News
fields = (
'id',
'duplication_date',
'country',
)
class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer,
NewsDetailSerializer):
"""News detail serializer for back-office users."""
news_type_id = serializers.PrimaryKeyRelatedField(
source='news_type', write_only=True,
queryset=models.NewsType.objects.all())
country_id = serializers.PrimaryKeyRelatedField(
source='country', write_only=True,
queryset=location_models.Country.objects.all())
site_id = serializers.PrimaryKeyRelatedField(
source='site', write_only=True,
queryset=SiteSettings.objects.all())
template_display = serializers.CharField(source='get_template_display',
read_only=True)
duplicates = NewsBackOfficeDuplicationInfoSerializer(many=True, allow_null=True, read_only=True)
class Meta(NewsBackOfficeBaseSerializer.Meta, NewsDetailSerializer.Meta):
"""Meta class."""
fields = NewsBackOfficeBaseSerializer.Meta.fields + \
NewsDetailSerializer.Meta.fields + (
'description',
'news_type_id',
'country_id',
'site_id',
'template',
'template_display',
'is_international',
'duplicates',
)
class NewsBackOfficeGallerySerializer(serializers.ModelSerializer):
"""Serializer class for model NewsGallery."""
class Meta:
"""Meta class"""
model = models.NewsGallery
fields = [
'id',
'is_main',
]
@property
def request_kwargs(self):
"""Get url kwargs from request."""
return self.context.get('request').parser_context.get('kwargs')
def create(self, validated_data):
news_pk = self.request_kwargs.get('pk')
image_id = self.request_kwargs.get('image_id')
qs = models.NewsGallery.objects.filter(image_id=image_id, news_id=news_pk)
instance = qs.first()
if instance:
qs.update(**validated_data)
return instance
return super().create(validated_data)
def validate(self, attrs):
"""Override validate method."""
news_pk = self.request_kwargs.get('pk')
image_id = self.request_kwargs.get('image_id')
news_qs = models.News.objects.filter(pk=news_pk)
image_qs = Image.objects.filter(id=image_id)
if not news_qs.exists():
raise serializers.ValidationError({'detail': _('News not found')})
if not image_qs.exists():
raise serializers.ValidationError({'detail': _('Image not found')})
news = news_qs.first()
image = image_qs.first()
# if image in news.gallery.all():
# raise serializers.ValidationError({'detail': _('Image is already added.')})
attrs['news'] = news
attrs['image'] = image
return attrs
class NewsFavoritesCreateSerializer(FavoritesCreateSerializer):
"""Serializer to favorite object w/ model News."""
def validate(self, attrs):
"""Overridden validate method"""
# Check establishment object
news_qs = models.News.objects.filter(slugs__values__contains=[self.slug])
# Check establishment obj by slug from lookup_kwarg
if not news_qs.exists():
raise serializers.ValidationError({'detail': _('Object not found.')})
else:
news = news_qs.first()
# Check existence in favorites
if news.favorites.filter(user=self.user).exists():
raise utils_exceptions.FavoritesError()
attrs['news'] = news
return attrs
def create(self, validated_data, *args, **kwargs):
"""Overridden create method"""
validated_data.update({
'user': self.user,
'content_object': validated_data.pop('news')
})
return super().create(validated_data)
class NewsCarouselCreateSerializer(CarouselCreateSerializer):
"""Serializer to carousel object w/ model News."""
def validate(self, attrs):
news = models.News.objects.filter(pk=self.pk).first()
if not news:
raise serializers.ValidationError({'detail': _('Object not found.')})
if news.carousels.exists():
raise utils_exceptions.CarouselError()
attrs['news'] = news
return attrs
def create(self, validated_data, *args, **kwargs):
validated_data.update({
'content_object': validated_data.pop('news')
})
return super().create(validated_data)
class NewsCloneCreateSerializer(NewsBackOfficeBaseSerializer,
NewsDetailSerializer):
"""Serializer for creating news clone."""
template_display = serializers.CharField(source='get_template_display',
read_only=True)
duplicates = NewsBackOfficeDuplicationInfoSerializer(many=True, allow_null=True, read_only=True)
class Meta(NewsBackOfficeBaseSerializer.Meta, NewsDetailSerializer.Meta):
fields = NewsBackOfficeBaseSerializer.Meta.fields + NewsDetailSerializer.Meta.fields + (
'template_display',
'duplicates',
)
read_only_fields = fields
def create(self, validated_data):
kwargs = self.context.get('request').parser_context.get('kwargs')
instance = get_object_or_404(models.News, pk=kwargs['pk'])
new_country = get_object_or_404(location_models.Country, code=kwargs['country_code'])
view_count_model = rating_models.ViewCount.objects.create(count=0)
instance.create_duplicate(new_country, view_count_model)
return get_object_or_404(models.News, pk=kwargs['pk'])