From e67d7767a1748b7933eba3047c5fe664b5e28859 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Tue, 17 Sep 2019 17:33:07 +0300 Subject: [PATCH 1/4] Elasticsearch: establishment address. Filter by country_id, country_code --- apps/location/models.py | 5 ++++ .../search_indexes/documents/establishment.py | 28 +++++++++++++++++++ apps/search_indexes/serializers.py | 2 ++ apps/search_indexes/utils.py | 1 + apps/search_indexes/views.py | 6 ++++ apps/utils/models.py | 20 +++++++++++++ 6 files changed, 62 insertions(+) diff --git a/apps/location/models.py b/apps/location/models.py index 7d7cd8a2..7084385f 100644 --- a/apps/location/models.py +++ b/apps/location/models.py @@ -104,6 +104,11 @@ class Address(models.Model): def longitude(self): return self.coordinates.x + @property + def location_field_indexing(self): + return {'lat': self.latitude, + 'lon': self.longitude} + # todo: Make recalculate price levels @receiver(post_save, sender=Country) diff --git a/apps/search_indexes/documents/establishment.py b/apps/search_indexes/documents/establishment.py index a12e23c8..a260c7f5 100644 --- a/apps/search_indexes/documents/establishment.py +++ b/apps/search_indexes/documents/establishment.py @@ -21,6 +21,34 @@ class EstablishmentDocument(Document): 'label': fields.ObjectField(attr='label') }, multi=True) + address = fields.ObjectField( + properties={ + 'id': fields.IntegerField(), + 'street_name_1': fields.TextField( + fields={'raw': fields.KeywordField()} + ), + 'street_name_2': fields.TextField( + fields={'raw': fields.KeywordField()} + ), + 'number': fields.IntegerField(), + 'location': fields.GeoPointField(attr='location_field_indexing'), + 'city': fields.ObjectField( + properties={ + 'id': fields.IntegerField(), + 'name': fields.KeywordField(), + 'is_island': fields.BooleanField(), + 'country': fields.ObjectField( + properties={ + 'id': fields.IntegerField(), + 'name': fields.ObjectField(attr='name_indexing', + properties=OBJECT_FIELD_PROPERTIES), + 'code': fields.KeywordField(), + } + ), + } + ), + } + ) class Django: diff --git a/apps/search_indexes/serializers.py b/apps/search_indexes/serializers.py index f4c27c9b..ed8b65eb 100644 --- a/apps/search_indexes/serializers.py +++ b/apps/search_indexes/serializers.py @@ -40,6 +40,7 @@ class NewsDocumentSerializer(DocumentSerializer): return get_translated_value(obj.description) +# todo: country_name_translated class EstablishmentDocumentSerializer(DocumentSerializer): """Establishment document serializer.""" @@ -58,6 +59,7 @@ class EstablishmentDocumentSerializer(DocumentSerializer): 'price_level', 'description_translated', 'tags', + 'address', ) @staticmethod diff --git a/apps/search_indexes/utils.py b/apps/search_indexes/utils.py index a3cfac87..93be9e81 100644 --- a/apps/search_indexes/utils.py +++ b/apps/search_indexes/utils.py @@ -7,6 +7,7 @@ from utils.models import get_current_language OBJECT_FIELD_PROPERTIES = { 'en-GB': fields.TextField(analyzer='english'), 'ru-RU': fields.TextField(analyzer='russian'), + 'fr-FR': fields.TextField(analyzer='french'), } diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 5dbaf8fd..9f7164d0 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -78,4 +78,10 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet): constants.LOOKUP_QUERY_LTE, ] }, + 'country_id': { + 'field': 'address.city.country.id' + }, + 'country': { + 'field': 'address.city.country.code' + } } diff --git a/apps/utils/models.py b/apps/utils/models.py index 22a7de98..92db5c47 100644 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -55,6 +55,24 @@ def translate_field(self, field_name): return translate +# todo: refactor this +class IndexJSON: + + def __getattr__(self, item): + return None + + +def index_field(self, field_name): + def index(self): + field = getattr(self, field_name) + obj = IndexJSON() + if isinstance(field, dict): + for key, value in field.items(): + setattr(obj, key, value) + return obj + return index + + class TranslatedFieldsMixin: """Translated Fields mixin""" @@ -69,6 +87,8 @@ class TranslatedFieldsMixin: if isinstance(field, TJSONField): setattr(cls, f'{field.name}_translated', property(translate_field(self, field_name))) + setattr(cls, f'{field_name}_indexing', + property(index_field(self, field_name))) def __str__(self): """Overrided __str__ method.""" From 2908286e6c6cd31be4e4bc94f76b7cf9baed6ce8 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Wed, 18 Sep 2019 10:50:00 +0300 Subject: [PATCH 2/4] price_level & toque_number settings --- apps/search_indexes/__init__.py | 1 + .../search_indexes/documents/establishment.py | 7 ++-- apps/search_indexes/signals.py | 33 +++++++++++++++++++ apps/search_indexes/views.py | 2 ++ 4 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 apps/search_indexes/signals.py diff --git a/apps/search_indexes/__init__.py b/apps/search_indexes/__init__.py index e69de29b..f610ac3f 100644 --- a/apps/search_indexes/__init__.py +++ b/apps/search_indexes/__init__.py @@ -0,0 +1 @@ +from search_indexes.signals import update_document \ No newline at end of file diff --git a/apps/search_indexes/documents/establishment.py b/apps/search_indexes/documents/establishment.py index a260c7f5..b82bc579 100644 --- a/apps/search_indexes/documents/establishment.py +++ b/apps/search_indexes/documents/establishment.py @@ -14,7 +14,8 @@ EstablishmentIndex.settings(number_of_shards=1, number_of_replicas=1) class EstablishmentDocument(Document): """Establishment document.""" - description = fields.ObjectField(properties=OBJECT_FIELD_PROPERTIES) + description = fields.ObjectField(attr='description_indexing', + properties=OBJECT_FIELD_PROPERTIES) tags = fields.ObjectField( properties={ 'id': fields.IntegerField(attr='id'), @@ -56,13 +57,9 @@ class EstablishmentDocument(Document): fields = ( 'id', 'name', - 'public_mark', 'toque_number', 'price_level', ) - def prepare_description(self, instance): - return instance.description - def prepare_tags(self, instance): return instance.tags_indexing diff --git a/apps/search_indexes/signals.py b/apps/search_indexes/signals.py new file mode 100644 index 00000000..21618155 --- /dev/null +++ b/apps/search_indexes/signals.py @@ -0,0 +1,33 @@ +"""Search indexes app signals.""" +from django.db.models.signals import post_save, post_delete +from django.dispatch import receiver +from django_elasticsearch_dsl.registries import registry + + +@receiver(post_save) +def update_document(sender, **kwargs): + from establishment.models import Establishment + app_label = sender._meta.app_label + model_name = sender._meta.model_name + instance = kwargs['instance'] + + if app_label == 'location': + if model_name == 'country': + establishments = Establishment.objects.filter( + address__city__country=instance) + for establishment in establishments: + registry.update(establishment) + + if model_name == 'city': + establishments = Establishment.objects.filter( + address__city=instance) + for establishment in establishments: + registry.update(establishment) + + if model_name == 'Address': + establishments = Establishment.objects.filter( + address=instance) + for establishment in establishments: + registry.update(establishment) + +# todo: delete document diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 9f7164d0..31d982a4 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -66,6 +66,7 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet): constants.LOOKUP_QUERY_GTE, constants.LOOKUP_QUERY_LT, constants.LOOKUP_QUERY_LTE, + constants.LOOKUP_QUERY_IN, ] }, 'price_level': { @@ -76,6 +77,7 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet): constants.LOOKUP_QUERY_GTE, constants.LOOKUP_QUERY_LT, constants.LOOKUP_QUERY_LTE, + constants.LOOKUP_QUERY_IN, ] }, 'country_id': { From 784728d1558edbca8439d84ec83587fa5414ec41 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Wed, 18 Sep 2019 11:21:06 +0300 Subject: [PATCH 3/4] Facebook auth return user email; fixed URL in templates --- apps/account/serializers/web.py | 3 +-- apps/authorization/views/common.py | 2 +- project/settings/base.py | 4 ++++ project/templates/account/change_email.html | 2 +- project/templates/account/password_reset_email.html | 2 +- project/templates/authorization/confirm_email.html | 3 +-- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/account/serializers/web.py b/apps/account/serializers/web.py index d325cea6..8d6fadf7 100644 --- a/apps/account/serializers/web.py +++ b/apps/account/serializers/web.py @@ -1,6 +1,5 @@ """Serializers for account web""" from django.contrib.auth import password_validation as password_validators -from django.utils.translation import gettext_lazy as _ from rest_framework import serializers from account import models @@ -25,7 +24,7 @@ class PasswordResetSerializer(serializers.Serializer): if not user.is_authenticated: if not username_or_email: - raise serializers.ValidationError(_('username or email not in request body.')) + raise utils_exceptions.UserNotFoundError() filters = {} if username_validator(username_or_email): diff --git a/apps/authorization/views/common.py b/apps/authorization/views/common.py index 98f79bd9..4231ed7a 100644 --- a/apps/authorization/views/common.py +++ b/apps/authorization/views/common.py @@ -116,7 +116,7 @@ class OAuth2SignUpView(OAuth2ViewMixin, JWTGenericViewMixin): source = serializer.validated_data.get('source') request_data.update({ 'grant_type': settings.OAUTH2_SOCIAL_AUTH_GRANT_TYPE, - 'backend': settings.OAUTH2_SOCIAL_AUTH_BACKEND_NAME + 'backend': settings.OAUTH2_SOCIAL_AUTH_BACKEND_NAME, }) # Use the rest framework `.data` to fake the post body of the django request. diff --git a/project/settings/base.py b/project/settings/base.py index 71fbf147..1a54b1b7 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -256,6 +256,10 @@ OAUTH2_PROVIDER_APPLICATION_MODEL = 'authorization.Application' # Facebook configuration SOCIAL_AUTH_FACEBOOK_KEY = '386843648701452' SOCIAL_AUTH_FACEBOOK_SECRET = 'a71cf0bf3980843a8f1ea74c6d805fd7' +SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', ] +SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = { + 'fields': 'id, name, email', +} # SMS Settings SMS_EXPIRATION = 5 diff --git a/project/templates/account/change_email.html b/project/templates/account/change_email.html index 40c1b227..0a257ed6 100644 --- a/project/templates/account/change_email.html +++ b/project/templates/account/change_email.html @@ -3,7 +3,7 @@ {% trans "Please go to the following page for confirmation new email address:" %} -https://{{ country_code }}.{{ domain_uri }}/registered/{{ uidb64 }}/{{ token }}/ +https://{{ country_code }}.{{ domain_uri }}/registered/{{ uidb64 }}/{{ token }}/ {% trans "Thanks for using our site!" %} diff --git a/project/templates/account/password_reset_email.html b/project/templates/account/password_reset_email.html index ee84fd0b..9fb3fbf3 100644 --- a/project/templates/account/password_reset_email.html +++ b/project/templates/account/password_reset_email.html @@ -3,7 +3,7 @@ {% trans "Please go to the following page and choose a new password:" %} -https://{{ country_code }}.{{ domain_uri }}/recovery/{{ uidb64 }}/{{ token }}/ +https://{{ country_code }}.{{ domain_uri }}/recovery/{{ uidb64 }}/{{ token }}/ {% trans "Thanks for using our site!" %} diff --git a/project/templates/authorization/confirm_email.html b/project/templates/authorization/confirm_email.html index f3bbd50e..3e51add7 100644 --- a/project/templates/authorization/confirm_email.html +++ b/project/templates/authorization/confirm_email.html @@ -2,8 +2,7 @@ {% blocktrans %}You're receiving this email because you trying to register new account at {{ site_name }}.{% endblocktrans %} {% trans "Please confirm your email address to complete the registration:" %} - -https://{{ country_code }}.{{ domain_uri }}/registered/{{ uidb64 }}/{{ token }}/ +https://{{ country_code }}.{{ domain_uri }}/registered/{{ uidb64 }}/{{ token }}/ {% trans "Thanks for using our site!" %} From 61fc78eeb9ddd14c3b3b961bf1355321e24db264 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Wed, 18 Sep 2019 11:28:00 +0300 Subject: [PATCH 4/4] fixed cookie settings for stage server --- apps/utils/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/utils/views.py b/apps/utils/views.py index 9af89360..8333b34a 100644 --- a/apps/utils/views.py +++ b/apps/utils/views.py @@ -67,7 +67,7 @@ class JWTGenericViewMixin(generics.GenericAPIView): # todo: remove config for develop from os import environ configuration = environ.get('SETTINGS_CONFIGURATION', None) - if configuration == 'development': + if configuration == 'development' or configuration == 'stage': response.set_cookie(key=cookie.key, value=cookie.value, secure=cookie.secure,