Merge branch 'develop' into feature/guides

This commit is contained in:
Anatoly 2019-12-18 12:03:45 +03:00
commit 2401763e6c
12 changed files with 96 additions and 18 deletions

View File

@ -18,7 +18,7 @@ class CollectionViewMixin(generics.GenericAPIView):
"""Override get_queryset method.""" """Override get_queryset method."""
return models.Collection.objects.published() \ return models.Collection.objects.published() \
.by_country_code(code=self.request.country_code) \ .by_country_code(code=self.request.country_code) \
.order_by('-on_top', '-modified') .order_by('-on_top', '-created')
class GuideViewMixin(generics.GenericAPIView): class GuideViewMixin(generics.GenericAPIView):

View File

@ -37,6 +37,13 @@ def determine_country_code(request):
return country_code.lower() return country_code.lower()
def determine_country_name(request):
"""Determine country name."""
META = request.META
return META.get('X-GeoIP-Country-Name',
META.get('HTTP_X_GEOIP_COUNTRY_NAME'))
def determine_coordinates(request): def determine_coordinates(request):
META = request.META META = request.META
longitude = META.get('X-GeoIP-Longitude', longitude = META.get('X-GeoIP-Longitude',

View File

@ -210,6 +210,25 @@ class CarouselQuerySet(models.QuerySet):
"""Filter collection by country code.""" """Filter collection by country code."""
return self.filter(country__code=code) return self.filter(country__code=code)
def create_or_destroy(self, instance_to_bind, country):
"""Creates or destroys Carousel instance depending on instance fields"""
toggle = True
kwargs = {
'content_type': ContentType.objects.get_for_model(instance_to_bind),
'object_id': instance_to_bind.pk,
'country': country,
}
if toggle is None:
return
elif toggle:
kwargs.update({
'is_parse': True,
'active': True,
})
self.create(**kwargs)
else:
self.filter(**kwargs).delete()
class Carousel(models.Model): class Carousel(models.Model):
"""Carousel model.""" """Carousel model."""
@ -279,6 +298,11 @@ class Carousel(models.Model):
@property @property
def slug(self): def slug(self):
if hasattr(self.content_object, 'slugs'):
try:
return next(iter(self.content_object.slugs.values()))
except StopIteration:
return None
if hasattr(self.content_object, 'slug'): if hasattr(self.content_object, 'slug'):
return self.content_object.slug return self.content_object.slug

View File

@ -85,8 +85,9 @@ class DetermineLocation(generics.GenericAPIView):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
longitude, latitude = methods.determine_coordinates(request) longitude, latitude = methods.determine_coordinates(request)
city = methods.determine_user_city(request) city = methods.determine_user_city(request)
if longitude and latitude and city: country_name = methods.determine_country_name(request)
return Response(data={'latitude': latitude, 'longitude': longitude, 'city': city}) if longitude and latitude and city and country_name:
else: return Response(data={'latitude': latitude, 'longitude': longitude,
'city': city, 'country_name': country_name})
raise Http404 raise Http404

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.7 on 2019-12-17 17:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('news', '0044_auto_20191216_2044'),
]
operations = [
migrations.AddField(
model_name='news',
name='must_of_the_week',
field=models.BooleanField(default=False),
),
]

View File

@ -223,6 +223,7 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi
verbose_name=_('Duplication datetime')) verbose_name=_('Duplication datetime'))
duplication_uuid = models.UUIDField(default=uuid.uuid4, editable=True, unique=False, duplication_uuid = models.UUIDField(default=uuid.uuid4, editable=True, unique=False,
verbose_name=_('Field to detect doubles')) verbose_name=_('Field to detect doubles'))
must_of_the_week = models.BooleanField(default=False, verbose_name=_('Show in the carousel'))
objects = NewsQuerySet.as_manager() objects = NewsQuerySet.as_manager()
class Meta: class Meta:
@ -248,6 +249,11 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi
"""Duplicates for this news item excluding same country code labeled""" """Duplicates for this news item excluding same country code labeled"""
return News.objects.filter(duplication_uuid=self.duplication_uuid).exclude(country=self.country) return News.objects.filter(duplication_uuid=self.duplication_uuid).exclude(country=self.country)
@property
def has_any_desc_active(self):
"""Detects whether news item has any active description"""
return any(list(map(lambda v: v.lower() == 'true', self.locale_to_description_is_active.values())))
@property @property
def is_publish(self): def is_publish(self):
return self.state in self.PUBLISHED_STATES return self.state in self.PUBLISHED_STATES

View File

@ -5,7 +5,7 @@ from rest_framework.fields import SerializerMethodField
from account.serializers.common import UserBaseSerializer from account.serializers.common import UserBaseSerializer
from gallery.models import Image from gallery.models import Image
from main.models import SiteSettings from main.models import SiteSettings, Carousel
from location import models as location_models from location import models as location_models
from location.serializers import CountrySimpleSerializer, AddressBaseSerializer from location.serializers import CountrySimpleSerializer, AddressBaseSerializer
from news import models from news import models
@ -185,6 +185,7 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
'locale_to_description_is_active', 'locale_to_description_is_active',
'is_published', 'is_published',
'duplication_date', 'duplication_date',
'must_of_the_week',
) )
extra_kwargs = { extra_kwargs = {
'backoffice_title': {'allow_null': False}, 'backoffice_title': {'allow_null': False},
@ -199,7 +200,9 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
slugs__values__contains=list(slugs.values()) slugs__values__contains=list(slugs.values())
).exists(): ).exists():
raise serializers.ValidationError({'slugs': _('News with this slug already exists.')}) raise serializers.ValidationError({'slugs': _('News with this slug already exists.')})
return super().create(validated_data) instance = super().create(validated_data)
Carousel.objects.create_or_destroy(instance, instance.address.city.country)
return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
slugs = validated_data.get('slugs') slugs = validated_data.get('slugs')
@ -208,7 +211,10 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
slugs__values__contains=list(slugs.values()) slugs__values__contains=list(slugs.values())
).exclude(pk=instance.pk).exists(): ).exclude(pk=instance.pk).exists():
raise serializers.ValidationError({'slugs': _('News with this slug already exists.')}) raise serializers.ValidationError({'slugs': _('News with this slug already exists.')})
return super().update(instance, validated_data) 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): class NewsBackOfficeDuplicationInfoSerializer(serializers.ModelSerializer):
@ -380,5 +386,5 @@ class NewsCloneCreateSerializer(NewsBackOfficeBaseSerializer,
new_country = get_object_or_404(location_models.Country, code=kwargs['country_code']) new_country = get_object_or_404(location_models.Country, code=kwargs['country_code'])
view_count_model = rating_models.ViewCount.objects.create(count=0) view_count_model = rating_models.ViewCount.objects.create(count=0)
instance.create_duplicate(new_country, view_count_model) instance.create_duplicate(new_country, view_count_model)
return instance return get_object_or_404(models.News, pk=kwargs['pk'])

View File

@ -54,7 +54,8 @@ class NewsListView(NewsMixinView, generics.ListAPIView):
'international_preferred': True, 'international_preferred': True,
'locale': locale, 'locale': locale,
}) })
return super().get_queryset(*args, **kwargs) return super().get_queryset(*args, **kwargs)\
.filter(locale_to_description_is_active__values__contains=['True'])
class NewsDetailView(NewsMixinView, generics.RetrieveAPIView): class NewsDetailView(NewsMixinView, generics.RetrieveAPIView):

View File

@ -3,6 +3,7 @@ from django.conf import settings
from django_elasticsearch_dsl import Document, Index, fields from django_elasticsearch_dsl import Document, Index, fields
from search_indexes.utils import OBJECT_FIELD_PROPERTIES from search_indexes.utils import OBJECT_FIELD_PROPERTIES
from news import models from news import models
from json import dumps
NewsIndex = Index(settings.ELASTICSEARCH_INDEX_NAMES.get(__name__, 'news')) NewsIndex = Index(settings.ELASTICSEARCH_INDEX_NAMES.get(__name__, 'news'))
@ -17,7 +18,7 @@ class NewsDocument(Document):
'name': fields.KeywordField()}) 'name': fields.KeywordField()})
title = fields.ObjectField(attr='title_indexing', title = fields.ObjectField(attr='title_indexing',
properties=OBJECT_FIELD_PROPERTIES) properties=OBJECT_FIELD_PROPERTIES)
slugs = fields.ObjectField(properties=OBJECT_FIELD_PROPERTIES) slugs = fields.KeywordField()
backoffice_title = fields.TextField(analyzer='english') backoffice_title = fields.TextField(analyzer='english')
subtitle = fields.ObjectField(attr='subtitle_indexing', subtitle = fields.ObjectField(attr='subtitle_indexing',
properties=OBJECT_FIELD_PROPERTIES) properties=OBJECT_FIELD_PROPERTIES)
@ -45,9 +46,10 @@ class NewsDocument(Document):
multi=True) multi=True)
favorites_for_users = fields.ListField(field=fields.IntegerField()) favorites_for_users = fields.ListField(field=fields.IntegerField())
start = fields.DateField(attr='start') start = fields.DateField(attr='start')
has_any_desc_active = fields.BooleanField()
def prepare_slugs(self, instance): def prepare_slugs(self, instance):
return {locale: instance.slugs.get(locale) for locale in OBJECT_FIELD_PROPERTIES} return dumps(instance.slugs or {})
class Django: class Django:

View File

@ -6,6 +6,7 @@ from news.serializers import NewsTypeSerializer
from search_indexes.documents import EstablishmentDocument, NewsDocument from search_indexes.documents import EstablishmentDocument, NewsDocument
from search_indexes.documents.product import ProductDocument from search_indexes.documents.product import ProductDocument
from search_indexes.utils import get_translated_value from search_indexes.utils import get_translated_value
from json import loads
class TagsDocumentSerializer(serializers.Serializer): class TagsDocumentSerializer(serializers.Serializer):
@ -243,7 +244,7 @@ class NewsDocumentSerializer(InFavoritesMixin, DocumentSerializer):
@staticmethod @staticmethod
def get_slug(obj): def get_slug(obj):
return get_translated_value(obj.slugs) return get_translated_value(loads(obj.slugs))
@staticmethod @staticmethod
def get_title_translated(obj): def get_title_translated(obj):

View File

@ -17,6 +17,11 @@ from utils.pagination import ESDocumentPagination
class NewsDocumentViewSet(BaseDocumentViewSet): class NewsDocumentViewSet(BaseDocumentViewSet):
"""News document ViewSet.""" """News document ViewSet."""
def get_queryset(self):
qs = super(NewsDocumentViewSet, self).get_queryset()
qs = qs.filter('match', has_any_desc_active=True)
return qs
document = NewsDocument document = NewsDocument
lookup_field = 'slug' lookup_field = 'slug'
pagination_class = ESDocumentPagination pagination_class = ESDocumentPagination

View File

@ -67,16 +67,23 @@ def get_default_locale():
settings.FALLBACK_LOCALE settings.FALLBACK_LOCALE
def translate_field(self, field_name): def translate_field(self, field_name, toggle_field_name=None):
def translate(self): def translate(self):
field = getattr(self, field_name) field = getattr(self, field_name)
toggler = getattr(self, toggle_field_name, None)
if isinstance(field, dict): if isinstance(field, dict):
if toggler:
field = {locale: v for locale, v in field.items() if toggler.get(locale) in [True, 'True', 'true']}
value = field.get(to_locale(get_language())) value = field.get(to_locale(get_language()))
# fallback # fallback
if value is None: if value is None:
value = field.get(get_default_locale()) value = field.get(get_default_locale())
if value is None: if value is None:
value = field.get(next(iter(field.keys()), None)) try:
value = next(iter(field.values()))
except StopIteration:
# field values are absent
return None
return value return value
return None return None
return translate return translate
@ -114,7 +121,7 @@ class TranslatedFieldsMixin:
field_name = field.name field_name = field.name
if isinstance(field, TJSONField): if isinstance(field, TJSONField):
setattr(cls, f'{field.name}_translated', setattr(cls, f'{field.name}_translated',
property(translate_field(self, field_name))) property(translate_field(self, field_name, f'locale_to_{field_name}_is_active')))
setattr(cls, f'{field_name}_indexing', setattr(cls, f'{field_name}_indexing',
property(index_field(self, field_name))) property(index_field(self, field_name)))