Merge branch 'develop' into feature/news-rating
This commit is contained in:
commit
aa9288d41c
|
|
@ -172,38 +172,6 @@ class ChangeEmailSerializer(serializers.ModelSerializer):
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class ConfirmEmailSerializer(serializers.ModelSerializer):
|
|
||||||
"""Confirm user email serializer"""
|
|
||||||
x = serializers.CharField(default=None)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Meta class"""
|
|
||||||
model = models.User
|
|
||||||
fields = (
|
|
||||||
'email',
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate(self, attrs):
|
|
||||||
"""Override validate method"""
|
|
||||||
email_confirmed = self.instance.email_confirmed
|
|
||||||
if email_confirmed:
|
|
||||||
raise utils_exceptions.EmailConfirmedError()
|
|
||||||
|
|
||||||
return attrs
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
"""
|
|
||||||
Override update method
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Send verification link on user email for change email address
|
|
||||||
if settings.USE_CELERY:
|
|
||||||
tasks.confirm_new_email_address.delay(instance.id)
|
|
||||||
else:
|
|
||||||
tasks.confirm_new_email_address(instance.id)
|
|
||||||
return instance
|
|
||||||
|
|
||||||
|
|
||||||
# Firebase Cloud Messaging serializers
|
# Firebase Cloud Messaging serializers
|
||||||
class FCMDeviceSerializer(serializers.ModelSerializer):
|
class FCMDeviceSerializer(serializers.ModelSerializer):
|
||||||
"""FCM Device model serializer"""
|
"""FCM Device model serializer"""
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,6 @@ app_name = 'account'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('user/', views.UserRetrieveUpdateView.as_view(), name='user-retrieve-update'),
|
path('user/', views.UserRetrieveUpdateView.as_view(), name='user-retrieve-update'),
|
||||||
path('change-password/', views.ChangePasswordView.as_view(), name='change-password'),
|
path('change-password/', views.ChangePasswordView.as_view(), name='change-password'),
|
||||||
|
path('email/confirm/', views.SendConfirmationEmailView.as_view(), name='send-confirm-email'),
|
||||||
path('email/confirm/<uidb64>/<token>/', views.ConfirmEmailView.as_view(), name='confirm-email'),
|
path('email/confirm/<uidb64>/<token>/', views.ConfirmEmailView.as_view(), name='confirm-email'),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
"""Common account views"""
|
"""Common account views"""
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.http import urlsafe_base64_decode
|
from django.utils.http import urlsafe_base64_decode
|
||||||
from fcm_django.models import FCMDevice
|
from fcm_django.models import FCMDevice
|
||||||
|
|
@ -9,6 +10,7 @@ from rest_framework.response import Response
|
||||||
|
|
||||||
from account import models
|
from account import models
|
||||||
from account.serializers import common as serializers
|
from account.serializers import common as serializers
|
||||||
|
from authorization.tasks import send_confirm_email
|
||||||
from utils import exceptions as utils_exceptions
|
from utils import exceptions as utils_exceptions
|
||||||
from utils.models import GMTokenGenerator
|
from utils.models import GMTokenGenerator
|
||||||
from utils.views import JWTGenericViewMixin
|
from utils.views import JWTGenericViewMixin
|
||||||
|
|
@ -38,19 +40,26 @@ class ChangePasswordView(generics.GenericAPIView):
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class SendConfirmationEmailView(JWTGenericViewMixin):
|
class SendConfirmationEmailView(generics.GenericAPIView):
|
||||||
"""Confirm email view."""
|
"""Confirm email view."""
|
||||||
serializer_class = serializers.ConfirmEmailSerializer
|
|
||||||
queryset = models.User.objects.all()
|
|
||||||
|
|
||||||
def patch(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
"""Implement PATCH-method"""
|
"""Override create method"""
|
||||||
# Get user instance
|
user = self.request.user
|
||||||
instance = self.request.user
|
country_code = self.request.country_code
|
||||||
|
|
||||||
serializer = self.get_serializer(data=request.data, instance=instance)
|
if user.email_confirmed:
|
||||||
serializer.is_valid(raise_exception=True)
|
raise utils_exceptions.EmailConfirmedError()
|
||||||
serializer.save()
|
|
||||||
|
# Send verification link on user email for change email address
|
||||||
|
if settings.USE_CELERY:
|
||||||
|
send_confirm_email.delay(
|
||||||
|
user_id=user.id,
|
||||||
|
country_code=country_code)
|
||||||
|
else:
|
||||||
|
send_confirm_email(
|
||||||
|
user_id=user.id,
|
||||||
|
country_code=country_code)
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,39 +76,6 @@ class SignupSerializer(serializers.ModelSerializer):
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
class ReconfirmSerializer(serializers.ModelSerializer):
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = account_models.User
|
|
||||||
fields = ('email',)
|
|
||||||
|
|
||||||
def validate_email(self, value):
|
|
||||||
"""Validate email"""
|
|
||||||
users = list(account_models.User.objects.filter(email=value.lower()).all())
|
|
||||||
if not users:
|
|
||||||
raise serializers.ValidationError(detail='User with mentioned email does not exist.')
|
|
||||||
users = list(filter(lambda user: not user.email_confirmed, users))
|
|
||||||
if not users:
|
|
||||||
raise serializers.ValidationError(detail='User with this email is confirmed.')
|
|
||||||
return value
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
"""Override create method"""
|
|
||||||
queryset = account_models.User.objects.all()
|
|
||||||
email = validated_data.get('email').lower()
|
|
||||||
country_code = self.context.get('request').country_code
|
|
||||||
obj = get_object_or_404(queryset, email=email)
|
|
||||||
if settings.USE_CELERY:
|
|
||||||
tasks.send_confirm_email.delay(
|
|
||||||
user_id=obj.id,
|
|
||||||
country_code=country_code)
|
|
||||||
else:
|
|
||||||
tasks.send_confirm_email(
|
|
||||||
user_id=obj.id,
|
|
||||||
country_code=country_code)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
|
|
||||||
class LoginByUsernameOrEmailSerializer(SourceSerializerMixin,
|
class LoginByUsernameOrEmailSerializer(SourceSerializerMixin,
|
||||||
serializers.ModelSerializer):
|
serializers.ModelSerializer):
|
||||||
"""Serializer for login user"""
|
"""Serializer for login user"""
|
||||||
|
|
|
||||||
|
|
@ -4,18 +4,19 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
|
|
||||||
from account import models as account_models
|
from account import models as account_models
|
||||||
|
from smtplib import SMTPException
|
||||||
|
|
||||||
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO)
|
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def send_confirm_email(user_id, country_code):
|
def send_confirm_email(user_id: int, country_code: str):
|
||||||
"""Send verification email to user."""
|
"""Send verification email to user."""
|
||||||
try:
|
try:
|
||||||
obj = account_models.User.objects.get(id=user_id)
|
obj = account_models.User.objects.get(id=user_id)
|
||||||
obj.send_email(subject=_('Email confirmation'),
|
obj.send_email(subject=_('Email confirmation'),
|
||||||
message=obj.confirm_email_template(country_code))
|
message=obj.confirm_email_template(country_code))
|
||||||
except:
|
except Exception as e:
|
||||||
logger.error(f'METHOD_NAME: {send_confirm_email.__name__}\n'
|
logger.error(f'METHOD_NAME: {send_confirm_email.__name__}\n'
|
||||||
f'DETAIL: Exception occurred for user: {user_id}')
|
f'DETAIL: user {user_id}, - {e}')
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ urlpatterns_oauth2 = [
|
||||||
|
|
||||||
urlpatterns_jwt = [
|
urlpatterns_jwt = [
|
||||||
path('signup/', views.SignUpView.as_view(), name='signup'),
|
path('signup/', views.SignUpView.as_view(), name='signup'),
|
||||||
path('signup/reconfirm/', views.ReconfirmView.as_view(), name='signup-reconfirm'),
|
|
||||||
path('signup/confirm/<uidb64>/<token>/', views.ConfirmationEmailView.as_view(),
|
path('signup/confirm/<uidb64>/<token>/', views.ConfirmationEmailView.as_view(),
|
||||||
name='signup-confirm'),
|
name='signup-confirm'),
|
||||||
path('login/', views.LoginByUsernameOrEmailView.as_view(), name='login'),
|
path('login/', views.LoginByUsernameOrEmailView.as_view(), name='login'),
|
||||||
|
|
|
||||||
|
|
@ -147,17 +147,6 @@ class SignUpView(generics.GenericAPIView):
|
||||||
return Response(status=status.HTTP_201_CREATED)
|
return Response(status=status.HTTP_201_CREATED)
|
||||||
|
|
||||||
|
|
||||||
class ReconfirmView(generics.CreateAPIView):
|
|
||||||
""" Resends confirmation email whether user's still not confirmed """
|
|
||||||
permission_classes = (permissions.AllowAny,)
|
|
||||||
serializer_class = serializers.ReconfirmSerializer
|
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
serializer = self.get_serializer(data=request.data)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
return Response(status=status.HTTP_201_CREATED)
|
|
||||||
|
|
||||||
|
|
||||||
class ConfirmationEmailView(JWTGenericViewMixin):
|
class ConfirmationEmailView(JWTGenericViewMixin):
|
||||||
"""View for confirmation email"""
|
"""View for confirmation email"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ from django.db import models
|
||||||
from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q
|
from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from elasticsearch_dsl import Q
|
||||||
from phonenumber_field.modelfields import PhoneNumberField
|
from phonenumber_field.modelfields import PhoneNumberField
|
||||||
|
|
||||||
from collection.models import Collection
|
from collection.models import Collection
|
||||||
|
|
@ -98,6 +99,16 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
else:
|
else:
|
||||||
return self.none()
|
return self.none()
|
||||||
|
|
||||||
|
def es_search(self, value, locale=None):
|
||||||
|
"""Search text via ElasticSearch."""
|
||||||
|
from search_indexes.documents import EstablishmentDocument
|
||||||
|
search = EstablishmentDocument.search().filter(
|
||||||
|
Q('match', name=value) |
|
||||||
|
Q('match', **{f'description.{locale}': value})
|
||||||
|
).execute()
|
||||||
|
ids = [result.meta.id for result in search]
|
||||||
|
return self.filter(id__in=ids)
|
||||||
|
|
||||||
def by_country_code(self, code):
|
def by_country_code(self, code):
|
||||||
"""Return establishments by country code"""
|
"""Return establishments by country code"""
|
||||||
return self.filter(address__city__country__code=code)
|
return self.filter(address__city__country__code=code)
|
||||||
|
|
@ -330,7 +341,6 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
||||||
raise ValidationError('Establishment type of subtype does not match')
|
raise ValidationError('Establishment type of subtype does not match')
|
||||||
self.establishment_subtypes.add(establishment_subtype)
|
self.establishment_subtypes.add(establishment_subtype)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def vintage_year(self):
|
def vintage_year(self):
|
||||||
last_review = self.reviews.by_status(Review.READY).last()
|
last_review = self.reviews.by_status(Review.READY).last()
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,7 @@ from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
from utils.models import BaseAttributes, TJSONField, TranslatedFieldsMixin
|
from utils.models import BaseAttributes, TJSONField, TranslatedFieldsMixin
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from rating.models import Rating
|
from rating.models import Rating
|
||||||
from random import sample as random_sample
|
|
||||||
|
|
||||||
|
|
||||||
class NewsType(models.Model):
|
class NewsType(models.Model):
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ EstablishmentIndex.settings(number_of_shards=1, number_of_replicas=1)
|
||||||
class EstablishmentDocument(Document):
|
class EstablishmentDocument(Document):
|
||||||
"""Establishment document."""
|
"""Establishment document."""
|
||||||
|
|
||||||
|
preview_image = fields.KeywordField(attr='preview_image_url')
|
||||||
description = fields.ObjectField(attr='description_indexing',
|
description = fields.ObjectField(attr='description_indexing',
|
||||||
properties=OBJECT_FIELD_PROPERTIES)
|
properties=OBJECT_FIELD_PROPERTIES)
|
||||||
establishment_type = fields.ObjectField(
|
establishment_type = fields.ObjectField(
|
||||||
|
|
@ -50,7 +51,9 @@ class EstablishmentDocument(Document):
|
||||||
fields={'raw': fields.KeywordField()}
|
fields={'raw': fields.KeywordField()}
|
||||||
),
|
),
|
||||||
'number': fields.IntegerField(),
|
'number': fields.IntegerField(),
|
||||||
'location': fields.GeoPointField(attr='location_field_indexing'),
|
'postal_code': fields.KeywordField(),
|
||||||
|
'coordinates': fields.GeoPointField(attr='location_field_indexing'),
|
||||||
|
# todo: remove if not used
|
||||||
'city': fields.ObjectField(
|
'city': fields.ObjectField(
|
||||||
properties={
|
properties={
|
||||||
'id': fields.IntegerField(),
|
'id': fields.IntegerField(),
|
||||||
|
|
@ -82,9 +85,10 @@ class EstablishmentDocument(Document):
|
||||||
fields = (
|
fields = (
|
||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
'toque_number',
|
'name_translated',
|
||||||
'price_level',
|
'price_level',
|
||||||
'preview_image_url',
|
'toque_number',
|
||||||
|
'public_mark',
|
||||||
'slug',
|
'slug',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,26 @@ NewsIndex.settings(number_of_shards=1, number_of_replicas=1)
|
||||||
class NewsDocument(Document):
|
class NewsDocument(Document):
|
||||||
"""News document."""
|
"""News document."""
|
||||||
|
|
||||||
news_type = fields.NestedField(properties={
|
news_type = fields.ObjectField(properties={'id': fields.IntegerField(),
|
||||||
'id': fields.IntegerField(),
|
'name': fields.KeywordField()})
|
||||||
'name': fields.KeywordField()
|
title = fields.ObjectField(attr='title_indexing',
|
||||||
})
|
properties=OBJECT_FIELD_PROPERTIES)
|
||||||
title = fields.ObjectField(properties=OBJECT_FIELD_PROPERTIES)
|
subtitle = fields.ObjectField(attr='subtitle_indexing',
|
||||||
subtitle = fields.ObjectField(properties=OBJECT_FIELD_PROPERTIES)
|
properties=OBJECT_FIELD_PROPERTIES)
|
||||||
description = fields.ObjectField(properties=OBJECT_FIELD_PROPERTIES)
|
description = fields.ObjectField(attr='description_indexing',
|
||||||
country = fields.NestedField(properties={
|
properties=OBJECT_FIELD_PROPERTIES)
|
||||||
'id': fields.IntegerField(),
|
country = fields.ObjectField(properties={'id': fields.IntegerField(),
|
||||||
'code': fields.KeywordField()
|
'code': fields.KeywordField()})
|
||||||
})
|
|
||||||
web_url = fields.KeywordField(attr='web_url')
|
web_url = fields.KeywordField(attr='web_url')
|
||||||
|
tags = fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(attr='metadata.id'),
|
||||||
|
'label': fields.ObjectField(attr='metadata.label_indexing',
|
||||||
|
properties=OBJECT_FIELD_PROPERTIES),
|
||||||
|
'category': fields.ObjectField(attr='metadata.category',
|
||||||
|
properties={'id': fields.IntegerField()})
|
||||||
|
},
|
||||||
|
multi=True)
|
||||||
|
|
||||||
class Django:
|
class Django:
|
||||||
|
|
||||||
|
|
@ -32,20 +40,19 @@ class NewsDocument(Document):
|
||||||
fields = (
|
fields = (
|
||||||
'id',
|
'id',
|
||||||
'playlist',
|
'playlist',
|
||||||
|
'start',
|
||||||
|
'end',
|
||||||
|
'slug',
|
||||||
|
'state',
|
||||||
|
'is_highlighted',
|
||||||
|
'image_url',
|
||||||
|
'preview_image_url',
|
||||||
|
'template',
|
||||||
)
|
)
|
||||||
related_models = [models.NewsType]
|
related_models = [models.NewsType]
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().published()
|
return super().get_queryset().published().with_base_related()
|
||||||
|
|
||||||
def prepare_title(self, instance):
|
|
||||||
return instance.title
|
|
||||||
|
|
||||||
def prepare_subtitle(self, instance):
|
|
||||||
return instance.subtitle
|
|
||||||
|
|
||||||
def prepare_description(self, instance):
|
|
||||||
return instance.description
|
|
||||||
|
|
||||||
def get_instances_from_related(self, related_instance):
|
def get_instances_from_related(self, related_instance):
|
||||||
"""If related_models is set, define how to retrieve the Car instance(s) from the related model.
|
"""If related_models is set, define how to retrieve the Car instance(s) from the related model.
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,42 @@
|
||||||
"""Search indexes serializers."""
|
"""Search indexes serializers."""
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
|
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
|
||||||
|
from news.serializers import NewsTypeSerializer
|
||||||
from search_indexes.documents import EstablishmentDocument, NewsDocument
|
from search_indexes.documents import EstablishmentDocument, NewsDocument
|
||||||
from search_indexes.utils import get_translated_value
|
from search_indexes.utils import get_translated_value
|
||||||
|
|
||||||
|
|
||||||
|
class TagsDocumentSerializer(serializers.Serializer):
|
||||||
|
"""Tags serializer for ES Document."""
|
||||||
|
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
label_translated = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_label_translated(self, obj):
|
||||||
|
return get_translated_value(obj.label)
|
||||||
|
|
||||||
|
|
||||||
|
class AddressDocumentSerializer(serializers.Serializer):
|
||||||
|
"""Address serializer for ES Document."""
|
||||||
|
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
street_name_1 = serializers.CharField()
|
||||||
|
street_name_2 = serializers.CharField()
|
||||||
|
number = serializers.IntegerField()
|
||||||
|
postal_code = serializers.CharField()
|
||||||
|
latitude = serializers.FloatField(allow_null=True, source='coordinates.lat')
|
||||||
|
longitude = serializers.FloatField(allow_null=True, source='coordinates.lon')
|
||||||
|
geo_lon = serializers.FloatField(allow_null=True, source='coordinates.lon')
|
||||||
|
geo_lat = serializers.FloatField(allow_null=True, source='coordinates.lat')
|
||||||
|
|
||||||
|
|
||||||
class NewsDocumentSerializer(DocumentSerializer):
|
class NewsDocumentSerializer(DocumentSerializer):
|
||||||
"""News document serializer."""
|
"""News document serializer."""
|
||||||
|
|
||||||
title_translated = serializers.SerializerMethodField(allow_null=True)
|
title_translated = serializers.SerializerMethodField(allow_null=True)
|
||||||
subtitle_translated = serializers.SerializerMethodField(allow_null=True)
|
subtitle_translated = serializers.SerializerMethodField(allow_null=True)
|
||||||
description_translated = serializers.SerializerMethodField(allow_null=True)
|
news_type = NewsTypeSerializer()
|
||||||
|
tags = TagsDocumentSerializer(many=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
@ -18,13 +44,14 @@ class NewsDocumentSerializer(DocumentSerializer):
|
||||||
document = NewsDocument
|
document = NewsDocument
|
||||||
fields = (
|
fields = (
|
||||||
'id',
|
'id',
|
||||||
'title',
|
|
||||||
'subtitle',
|
|
||||||
'description',
|
|
||||||
'web_url',
|
|
||||||
'title_translated',
|
'title_translated',
|
||||||
'subtitle_translated',
|
'subtitle_translated',
|
||||||
'description_translated',
|
'is_highlighted',
|
||||||
|
'image_url',
|
||||||
|
'preview_image_url',
|
||||||
|
'news_type',
|
||||||
|
'tags',
|
||||||
|
'slug',
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -35,18 +62,13 @@ class NewsDocumentSerializer(DocumentSerializer):
|
||||||
def get_subtitle_translated(obj):
|
def get_subtitle_translated(obj):
|
||||||
return get_translated_value(obj.subtitle)
|
return get_translated_value(obj.subtitle)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_description_translated(obj):
|
|
||||||
return get_translated_value(obj.description)
|
|
||||||
|
|
||||||
|
|
||||||
# todo: country_name_translated
|
|
||||||
class EstablishmentDocumentSerializer(DocumentSerializer):
|
class EstablishmentDocumentSerializer(DocumentSerializer):
|
||||||
"""Establishment document serializer."""
|
"""Establishment document serializer."""
|
||||||
|
|
||||||
description_translated = serializers.SerializerMethodField(allow_null=True)
|
address = AddressDocumentSerializer()
|
||||||
|
tags = TagsDocumentSerializer(many=True)
|
||||||
|
|
||||||
preview_image = serializers.URLField(source='preview_image_url')
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
||||||
|
|
@ -54,43 +76,40 @@ class EstablishmentDocumentSerializer(DocumentSerializer):
|
||||||
fields = (
|
fields = (
|
||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
'public_mark',
|
'name_translated',
|
||||||
'toque_number',
|
|
||||||
'price_level',
|
'price_level',
|
||||||
'description_translated',
|
'toque_number',
|
||||||
'tags',
|
'public_mark',
|
||||||
'address',
|
|
||||||
'collections',
|
|
||||||
'establishment_type',
|
|
||||||
'establishment_subtypes',
|
|
||||||
'preview_image',
|
|
||||||
'slug',
|
'slug',
|
||||||
|
'preview_image',
|
||||||
|
'address',
|
||||||
|
'tags',
|
||||||
|
# 'collections',
|
||||||
|
# 'establishment_type',
|
||||||
|
# 'establishment_subtypes',
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_description_translated(obj):
|
|
||||||
return get_translated_value(obj.description)
|
|
||||||
|
|
||||||
def to_representation(self, instance):
|
# def to_representation(self, instance):
|
||||||
ret = super().to_representation(instance)
|
# ret = super().to_representation(instance)
|
||||||
dict_merge = lambda a, b: a.update(b) or a
|
# dict_merge = lambda a, b: a.update(b) or a
|
||||||
|
#
|
||||||
ret['tags'] = map(lambda tag: dict_merge(tag, {'label_translated': get_translated_value(tag.pop('label'))}),
|
# ret['tags'] = map(lambda tag: dict_merge(tag, {'label_translated': get_translated_value(tag.pop('label'))}),
|
||||||
ret['tags'])
|
# ret['tags'])
|
||||||
ret['establishment_subtypes'] = map(
|
# ret['establishment_subtypes'] = map(
|
||||||
lambda subtype: dict_merge(subtype, {'name_translated': get_translated_value(subtype.pop('name'))}),
|
# lambda subtype: dict_merge(subtype, {'name_translated': get_translated_value(subtype.pop('name'))}),
|
||||||
ret['establishment_subtypes'])
|
# ret['establishment_subtypes'])
|
||||||
if ret.get('establishment_type'):
|
# if ret.get('establishment_type'):
|
||||||
ret['establishment_type']['name_translated'] = get_translated_value(ret['establishment_type'].pop('name'))
|
# ret['establishment_type']['name_translated'] = get_translated_value(ret['establishment_type'].pop('name'))
|
||||||
if ret.get('address'):
|
# if ret.get('address'):
|
||||||
ret['address']['city']['country']['name_translated'] = get_translated_value(
|
# ret['address']['city']['country']['name_translated'] = get_translated_value(
|
||||||
ret['address']['city']['country'].pop('name'))
|
# ret['address']['city']['country'].pop('name'))
|
||||||
location = ret['address'].pop('location')
|
# location = ret['address'].pop('location')
|
||||||
if location:
|
# if location:
|
||||||
ret['address']['geo_lon'] = location['lon']
|
# ret['address']['geo_lon'] = location['lon']
|
||||||
ret['address']['geo_lat'] = location['lat']
|
# ret['address']['geo_lat'] = location['lat']
|
||||||
|
#
|
||||||
ret['type'] = ret.pop('establishment_type')
|
# ret['type'] = ret.pop('establishment_type')
|
||||||
ret['subtypes'] = ret.pop('establishment_subtypes')
|
# ret['subtypes'] = ret.pop('establishment_subtypes')
|
||||||
|
#
|
||||||
return ret
|
# return ret
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
"""Search indexes app signals."""
|
"""Search indexes app signals."""
|
||||||
from django.db.models.signals import post_save, post_delete
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django_elasticsearch_dsl.registries import registry
|
from django_elasticsearch_dsl.registries import registry
|
||||||
|
|
||||||
|
|
@ -17,17 +17,65 @@ def update_document(sender, **kwargs):
|
||||||
address__city__country=instance)
|
address__city__country=instance)
|
||||||
for establishment in establishments:
|
for establishment in establishments:
|
||||||
registry.update(establishment)
|
registry.update(establishment)
|
||||||
|
|
||||||
if model_name == 'city':
|
if model_name == 'city':
|
||||||
establishments = Establishment.objects.filter(
|
establishments = Establishment.objects.filter(
|
||||||
address__city=instance)
|
address__city=instance)
|
||||||
for establishment in establishments:
|
for establishment in establishments:
|
||||||
registry.update(establishment)
|
registry.update(establishment)
|
||||||
|
|
||||||
if model_name == 'address':
|
if model_name == 'address':
|
||||||
establishments = Establishment.objects.filter(
|
establishments = Establishment.objects.filter(
|
||||||
address=instance)
|
address=instance)
|
||||||
for establishment in establishments:
|
for establishment in establishments:
|
||||||
registry.update(establishment)
|
registry.update(establishment)
|
||||||
|
|
||||||
# todo: delete document
|
if app_label == 'establishment':
|
||||||
|
if model_name == 'establishmenttype':
|
||||||
|
establishments = Establishment.objects.filter(
|
||||||
|
establishment_type=instance)
|
||||||
|
for establishment in establishments:
|
||||||
|
registry.update(establishment)
|
||||||
|
if model_name == 'establishmentsubtype':
|
||||||
|
establishments = Establishment.objects.filter(
|
||||||
|
establishment_subtypes=instance)
|
||||||
|
for establishment in establishments:
|
||||||
|
registry.update(establishment)
|
||||||
|
|
||||||
|
if app_label == 'main':
|
||||||
|
if model_name == 'metadata':
|
||||||
|
establishments = Establishment.objects.filter(tags__metadata=instance)
|
||||||
|
for establishment in establishments:
|
||||||
|
registry.update(establishment)
|
||||||
|
if model_name == 'metadatacontent':
|
||||||
|
establishments = Establishment.objects.filter(tags=instance)
|
||||||
|
for establishment in establishments:
|
||||||
|
registry.update(establishment)
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save)
|
||||||
|
def update_news(sender, **kwargs):
|
||||||
|
from news.models import News
|
||||||
|
app_label = sender._meta.app_label
|
||||||
|
model_name = sender._meta.model_name
|
||||||
|
instance = kwargs['instance']
|
||||||
|
|
||||||
|
if app_label == 'location':
|
||||||
|
if model_name == 'country':
|
||||||
|
qs = News.objects.filter(country=instance)
|
||||||
|
for news in qs:
|
||||||
|
registry.update(news)
|
||||||
|
|
||||||
|
if app_label == 'news':
|
||||||
|
if model_name == 'newstype':
|
||||||
|
qs = News.objects.filter(news_type=instance)
|
||||||
|
for news in qs:
|
||||||
|
registry.update(news)
|
||||||
|
|
||||||
|
if app_label == 'main':
|
||||||
|
if model_name == 'metadata':
|
||||||
|
qs = News.objects.filter(tags__metadata=instance)
|
||||||
|
for news in qs:
|
||||||
|
registry.update(news)
|
||||||
|
if model_name == 'metadatacontent':
|
||||||
|
qs = News.objects.filter(tags=instance)
|
||||||
|
for news in qs:
|
||||||
|
registry.update(news)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
"""Search indexes app views."""
|
"""Search indexes app views."""
|
||||||
from rest_framework import permissions
|
from rest_framework import permissions
|
||||||
from django_elasticsearch_dsl_drf import constants
|
from django_elasticsearch_dsl_drf import constants
|
||||||
from django_elasticsearch_dsl_drf.filter_backends import (FilteringFilterBackend,
|
from django_elasticsearch_dsl_drf.filter_backends import (
|
||||||
GeoSpatialFilteringFilterBackend)
|
FilteringFilterBackend,
|
||||||
|
GeoSpatialFilteringFilterBackend
|
||||||
|
)
|
||||||
from django_elasticsearch_dsl_drf.viewsets import BaseDocumentViewSet
|
from django_elasticsearch_dsl_drf.viewsets import BaseDocumentViewSet
|
||||||
|
|
||||||
from utils.pagination import ProjectPageNumberPagination
|
from utils.pagination import ProjectPageNumberPagination
|
||||||
|
|
@ -22,6 +24,7 @@ class NewsDocumentViewSet(BaseDocumentViewSet):
|
||||||
|
|
||||||
filter_backends = [
|
filter_backends = [
|
||||||
filters.CustomSearchFilterBackend,
|
filters.CustomSearchFilterBackend,
|
||||||
|
FilteringFilterBackend,
|
||||||
]
|
]
|
||||||
|
|
||||||
search_fields = (
|
search_fields = (
|
||||||
|
|
@ -35,6 +38,16 @@ class NewsDocumentViewSet(BaseDocumentViewSet):
|
||||||
'description',
|
'description',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
filter_fields = {
|
||||||
|
'tag': {
|
||||||
|
'field': 'tags.id',
|
||||||
|
'lookups': [
|
||||||
|
constants.LOOKUP_QUERY_IN,
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'slug': 'slug',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||||
"""Establishment document ViewSet."""
|
"""Establishment document ViewSet."""
|
||||||
|
|
@ -60,6 +73,7 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||||
'description',
|
'description',
|
||||||
)
|
)
|
||||||
filter_fields = {
|
filter_fields = {
|
||||||
|
'slug': 'slug',
|
||||||
'tag': {
|
'tag': {
|
||||||
'field': 'tags.id',
|
'field': 'tags.id',
|
||||||
'lookups': [constants.LOOKUP_QUERY_IN]
|
'lookups': [constants.LOOKUP_QUERY_IN]
|
||||||
|
|
@ -111,7 +125,7 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||||
|
|
||||||
geo_spatial_filter_fields = {
|
geo_spatial_filter_fields = {
|
||||||
'location': {
|
'location': {
|
||||||
'field': 'address.location',
|
'field': 'address.coordinates',
|
||||||
'lookups': [
|
'lookups': [
|
||||||
constants.LOOKUP_FILTER_GEO_BOUNDING_BOX,
|
constants.LOOKUP_FILTER_GEO_BOUNDING_BOX,
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ ELASTICSEARCH_DSL = {
|
||||||
|
|
||||||
|
|
||||||
ELASTICSEARCH_INDEX_NAMES = {
|
ELASTICSEARCH_INDEX_NAMES = {
|
||||||
# 'search_indexes.documents.news': 'development_news', # temporarily disabled
|
'search_indexes.documents.news': 'development_news', # temporarily disabled
|
||||||
'search_indexes.documents.establishment': 'development_establishment',
|
'search_indexes.documents.establishment': 'development_establishment',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user