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

@ -17,8 +17,8 @@ class CollectionViewMixin(generics.GenericAPIView):
def get_queryset(self):
"""Override get_queryset method."""
return models.Collection.objects.published() \
.by_country_code(code=self.request.country_code) \
.order_by('-on_top', '-modified')
.by_country_code(code=self.request.country_code) \
.order_by('-on_top', '-created')
class GuideViewMixin(generics.GenericAPIView):
@ -39,7 +39,7 @@ class CollectionHomePageView(CollectionListView):
def get_queryset(self):
"""Override get_queryset."""
return super(CollectionHomePageView, self).get_queryset() \
.filter_all_related_gt(3)
.filter_all_related_gt(3)
class CollectionDetailView(CollectionViewMixin, generics.RetrieveAPIView):

View File

@ -37,6 +37,13 @@ def determine_country_code(request):
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):
META = request.META
longitude = META.get('X-GeoIP-Longitude',

View File

@ -210,6 +210,25 @@ class CarouselQuerySet(models.QuerySet):
"""Filter collection by country 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):
"""Carousel model."""
@ -279,6 +298,11 @@ class Carousel(models.Model):
@property
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'):
return self.content_object.slug

View File

@ -85,8 +85,9 @@ class DetermineLocation(generics.GenericAPIView):
def get(self, request, *args, **kwargs):
longitude, latitude = methods.determine_coordinates(request)
city = methods.determine_user_city(request)
if longitude and latitude and city:
return Response(data={'latitude': latitude, 'longitude': longitude, 'city': city})
else:
raise Http404
country_name = methods.determine_country_name(request)
if longitude and latitude and city and country_name:
return Response(data={'latitude': latitude, 'longitude': longitude,
'city': city, 'country_name': country_name})
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'))
duplication_uuid = models.UUIDField(default=uuid.uuid4, editable=True, unique=False,
verbose_name=_('Field to detect doubles'))
must_of_the_week = models.BooleanField(default=False, verbose_name=_('Show in the carousel'))
objects = NewsQuerySet.as_manager()
class Meta:
@ -248,6 +249,11 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi
"""Duplicates for this news item excluding same country code labeled"""
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
def is_publish(self):
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 gallery.models import Image
from main.models import SiteSettings
from main.models import SiteSettings, Carousel
from location import models as location_models
from location.serializers import CountrySimpleSerializer, AddressBaseSerializer
from news import models
@ -185,6 +185,7 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
'locale_to_description_is_active',
'is_published',
'duplication_date',
'must_of_the_week',
)
extra_kwargs = {
'backoffice_title': {'allow_null': False},
@ -199,7 +200,9 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
slugs__values__contains=list(slugs.values())
).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):
slugs = validated_data.get('slugs')
@ -208,7 +211,10 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
slugs__values__contains=list(slugs.values())
).exclude(pk=instance.pk).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):
@ -380,5 +386,5 @@ class NewsCloneCreateSerializer(NewsBackOfficeBaseSerializer,
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 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,
'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):

View File

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

View File

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

View File

@ -17,6 +17,11 @@ from utils.pagination import ESDocumentPagination
class NewsDocumentViewSet(BaseDocumentViewSet):
"""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
lookup_field = 'slug'
pagination_class = ESDocumentPagination

View File

@ -67,16 +67,23 @@ def get_default_locale():
settings.FALLBACK_LOCALE
def translate_field(self, field_name):
def translate_field(self, field_name, toggle_field_name=None):
def translate(self):
field = getattr(self, field_name)
toggler = getattr(self, toggle_field_name, None)
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()))
# fallback
if value is None:
value = field.get(get_default_locale())
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 None
return translate
@ -114,7 +121,7 @@ class TranslatedFieldsMixin:
field_name = field.name
if isinstance(field, TJSONField):
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',
property(index_field(self, field_name)))