527 lines
18 KiB
Python
527 lines
18 KiB
Python
"""News app common serializers."""
|
|
from django.shortcuts import get_object_or_404
|
|
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 location import models as location_models
|
|
from location.serializers import AddressBaseSerializer, CountrySimpleSerializer
|
|
from main.models import SiteSettings
|
|
from news import models
|
|
from rating import models as rating_models
|
|
from tag.serializers import TagBaseSerializer
|
|
from utils import exceptions as utils_exceptions
|
|
from utils.models import get_current_locale, get_default_locale
|
|
from utils.serializers import (
|
|
CarouselCreateSerializer, FavoritesCreateSerializer, ImageBaseSerializer, ProjectModelSerializer, TranslatedField,
|
|
)
|
|
|
|
|
|
class AgendaSerializer(ProjectModelSerializer):
|
|
start_datetime = serializers.DateTimeField()
|
|
end_datetime = serializers.DateTimeField()
|
|
address = AddressBaseSerializer(read_only=True)
|
|
address_id = serializers.PrimaryKeyRelatedField(write_only=True, queryset=location_models.Address.objects.all(),
|
|
source='address')
|
|
event_name_translated = TranslatedField()
|
|
content_translated = TranslatedField()
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = models.Agenda
|
|
fields = (
|
|
'id',
|
|
'start_datetime',
|
|
'end_datetime',
|
|
'address',
|
|
'content_translated',
|
|
'event_name_translated',
|
|
'address_id',
|
|
)
|
|
|
|
|
|
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."""
|
|
default_image_url = serializers.ImageField(source='default_image.image',
|
|
allow_null=True)
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
|
|
model = models.NewsType
|
|
fields = ('id', 'name', 'default_image_url')
|
|
|
|
|
|
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',
|
|
'in_favorites',
|
|
)
|
|
|
|
|
|
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',
|
|
)
|
|
|
|
def update(self, instance, validated_data):
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
class NewsDetailWebSerializer(NewsDetailSerializer):
|
|
"""News detail serializer for web users.."""
|
|
|
|
same_theme = SerializerMethodField()
|
|
should_read = SerializerMethodField()
|
|
agenda = AgendaSerializer()
|
|
banner = NewsBannerSerializer()
|
|
in_favorites = serializers.BooleanField(read_only=True)
|
|
|
|
class Meta(NewsDetailSerializer.Meta):
|
|
"""Meta class."""
|
|
|
|
fields = NewsDetailSerializer.Meta.fields + (
|
|
'same_theme',
|
|
'should_read',
|
|
'agenda',
|
|
'banner',
|
|
'in_favorites',
|
|
)
|
|
|
|
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 NewsPreviewWebSerializer(NewsDetailSerializer):
|
|
"""News preview serializer for web users.."""
|
|
|
|
same_theme = SerializerMethodField()
|
|
agenda = AgendaSerializer()
|
|
banner = NewsBannerSerializer()
|
|
|
|
class Meta(NewsDetailSerializer.Meta):
|
|
"""Meta class."""
|
|
|
|
fields = NewsDetailSerializer.Meta.fields + (
|
|
'same_theme',
|
|
'agenda',
|
|
'banner',
|
|
)
|
|
|
|
def get_same_theme(self, obj):
|
|
return NewsSimilarListSerializer(obj.same_theme(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)
|
|
descriptions = serializers.ListField(required=False)
|
|
agenda = AgendaSerializer(required=False, allow_null=True)
|
|
state_display = serializers.CharField(source='get_state_display', 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',
|
|
'created',
|
|
'modified',
|
|
'descriptions',
|
|
'agenda',
|
|
'state',
|
|
'state_display',
|
|
)
|
|
extra_kwargs = {
|
|
'created': {'read_only': True},
|
|
'modified': {'read_only': True},
|
|
'duplication_date': {'read_only': True},
|
|
'locale_to_description_is_active': {'allow_null': False},
|
|
'must_of_the_week': {'read_only': True},
|
|
# 'state': {'read_only': True},
|
|
'state_display': {'read_only': True},
|
|
}
|
|
|
|
def validate(self, attrs):
|
|
"""Overridden validate method."""
|
|
if 'descriptions' in attrs:
|
|
descriptions = attrs.pop('descriptions')
|
|
locales = list(map(lambda x: x['locale'], descriptions))
|
|
status_to_bool = {
|
|
'active': True,
|
|
'inactive': False,
|
|
}
|
|
attrs['slugs'] = {obj['locale']: obj['slug'] for obj in descriptions if 'slug' in obj}
|
|
attrs['title'] = {obj['locale']: obj['title'] for obj in descriptions if 'title' in obj}
|
|
attrs['locale_to_description_is_active'] = {
|
|
obj['locale']: status_to_bool[obj['status']] for obj in descriptions
|
|
}
|
|
attrs['description'] = {obj['locale']: obj['text'] for obj in descriptions if 'text' in obj}
|
|
if self.context['request'].method == 'PATCH':
|
|
instance = models.News.objects.get(pk=self.context['request'].data['id'])
|
|
for key in ['slugs', 'title', 'locale_to_description_is_active', 'description']:
|
|
for locale in locales:
|
|
if locale not in attrs[key]:
|
|
attrs[key][locale] = getattr(instance, key).get(locale)
|
|
|
|
return attrs
|
|
|
|
def create(self, validated_data):
|
|
slugs = validated_data.get('slugs')
|
|
if slugs:
|
|
slugs_list = list(map(lambda x: x.lower(), slugs.values()))
|
|
slugs_set = set(slugs_list)
|
|
if models.News.objects.filter(
|
|
slugs__values__contains=list(slugs.values())
|
|
).exists() or len(slugs_list) != len(slugs_set):
|
|
raise serializers.ValidationError({'slugs': _('Slug should be unique')})
|
|
|
|
request = self.context.get("request")
|
|
if request and hasattr(request, "user"):
|
|
user = request.user
|
|
validated_data['created_by'] = user
|
|
|
|
agenda_data = validated_data.get('agenda')
|
|
agenda = None
|
|
|
|
if agenda_data is not None:
|
|
agenda_data['address_id'] = agenda_data.pop('address').pk
|
|
agenda_serializer = AgendaSerializer(data=agenda_data)
|
|
agenda_serializer.is_valid(raise_exception=True)
|
|
agenda = agenda_serializer.save()
|
|
|
|
instance = super().create(validated_data)
|
|
instance.agenda = agenda
|
|
instance.save()
|
|
|
|
return instance
|
|
|
|
def update(self, instance, validated_data):
|
|
slugs = validated_data.get('slugs')
|
|
slugs_list = list(map(lambda x: x.lower(), slugs.values() if slugs else ()))
|
|
slugs_set = set(slugs_list)
|
|
if slugs:
|
|
slugs_list = list(map(lambda x: x.lower(), slugs.values()))
|
|
slugs_set = set(slugs_list)
|
|
if models.News.objects.filter(
|
|
slugs__values__contains=list(slugs.values())
|
|
).exclude(pk=instance.pk).exists() or len(slugs_list) != len(slugs_set):
|
|
raise serializers.ValidationError({'slugs': _('Slug should be unique')})
|
|
|
|
agenda_data = validated_data.get('agenda')
|
|
agenda = instance.agenda
|
|
|
|
if agenda is None and agenda_data is not None:
|
|
agenda_data['address_id'] = agenda_data.pop('address').pk
|
|
agenda_serializer = AgendaSerializer(data=agenda_data)
|
|
agenda_serializer.is_valid(raise_exception=True)
|
|
agenda_serializer.save()
|
|
|
|
elif agenda_data is not None:
|
|
agenda.start_datetime = agenda_data.pop(
|
|
'start_datetime') if 'start_datetime' in agenda_data else agenda.start_datetime
|
|
agenda.end_datetime = agenda_data.pop(
|
|
'end_datetime') if 'end_datetime' in agenda_data else agenda.end_datetime
|
|
agenda.address = agenda_data.pop(
|
|
'address') if 'address' in agenda_data else agenda.address
|
|
agenda.event_name = agenda_data.pop(
|
|
'event_name') if 'event_time' in agenda_data else agenda.event_name
|
|
agenda.content = agenda_data.pop(
|
|
'content') if 'content' in agenda_data else agenda.content
|
|
agenda.save()
|
|
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
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)
|
|
agenda = AgendaSerializer(required=False, allow_null=True, read_only=True)
|
|
|
|
class Meta(NewsDetailSerializer.Meta, NewsBackOfficeBaseSerializer.Meta):
|
|
"""Meta class."""
|
|
|
|
fields = NewsBackOfficeBaseSerializer.Meta.fields + \
|
|
NewsDetailSerializer.Meta.fields + (
|
|
'description',
|
|
'news_type_id',
|
|
'country_id',
|
|
'site_id',
|
|
'template',
|
|
'template_display',
|
|
'is_international',
|
|
'duplicates',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
"""Overridden validate method."""
|
|
return super().validate(attrs)
|
|
|
|
def update(self, instance, validated_data):
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
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({
|
|
'country': validated_data['news'].country
|
|
})
|
|
validated_data.update({
|
|
'content_object': validated_data.pop('news'),
|
|
'is_parse': True,
|
|
'active': True,
|
|
})
|
|
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'])
|
|
|
|
|
|
class NewsStatesSerializer(serializers.Serializer):
|
|
value = serializers.IntegerField()
|
|
state_translated = serializers.CharField()
|