From c1f89515c5187c645cb213e0534e120224b3454c Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 01/18] Nested sitefeatures for new design --- .../main/migrations/0034_sitefeature_nested.py | 18 ++++++++++++++++++ apps/main/models.py | 1 + apps/main/serializers.py | 8 +++++--- apps/utils/serializers.py | 6 ++++++ 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 apps/main/migrations/0034_sitefeature_nested.py diff --git a/apps/main/migrations/0034_sitefeature_nested.py b/apps/main/migrations/0034_sitefeature_nested.py new file mode 100644 index 00000000..d699f209 --- /dev/null +++ b/apps/main/migrations/0034_sitefeature_nested.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.4 on 2019-11-07 14:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0033_auto_20191106_0744'), + ] + + operations = [ + migrations.AddField( + model_name='sitefeature', + name='nested', + field=models.ManyToManyField(to='main.SiteFeature'), + ), + ] diff --git a/apps/main/models.py b/apps/main/models.py index 9fee60b6..c9c694f9 100644 --- a/apps/main/models.py +++ b/apps/main/models.py @@ -151,6 +151,7 @@ class SiteFeature(ProjectBaseMixin): feature = models.ForeignKey(Feature, on_delete=models.PROTECT) published = models.BooleanField(default=False, verbose_name=_('Published')) main = models.BooleanField(default=False, verbose_name=_('Main')) + nested = models.ManyToManyField('self', symmetrical=False) objects = SiteFeatureQuerySet.as_manager() diff --git a/apps/main/serializers.py b/apps/main/serializers.py index 6f80178d..71bbd589 100644 --- a/apps/main/serializers.py +++ b/apps/main/serializers.py @@ -4,7 +4,7 @@ from rest_framework import serializers from advertisement.serializers.web import AdvertisementSerializer from location.serializers import CountrySerializer from main import models -from utils.serializers import ProjectModelSerializer, TranslatedField +from utils.serializers import ProjectModelSerializer, TranslatedField, RecursiveFieldSerializer class FeatureSerializer(serializers.ModelSerializer): @@ -27,6 +27,7 @@ class SiteFeatureSerializer(serializers.ModelSerializer): priority = serializers.IntegerField(source='feature.priority') route = serializers.CharField(source='feature.route.page_name') source = serializers.IntegerField(source='feature.source') + nested = RecursiveFieldSerializer(many=True, allow_null=True) class Meta: """Meta class.""" @@ -36,8 +37,9 @@ class SiteFeatureSerializer(serializers.ModelSerializer): 'slug', 'priority', 'route', - 'source' - ) + 'source', + 'nested', + ) class CurrencySerializer(ProjectModelSerializer): diff --git a/apps/utils/serializers.py b/apps/utils/serializers.py index bd7e8b8e..9a7be59d 100644 --- a/apps/utils/serializers.py +++ b/apps/utils/serializers.py @@ -98,3 +98,9 @@ class FavoritesCreateSerializer(serializers.ModelSerializer): @property def slug(self): return self.request.parser_context.get('kwargs').get('slug') + + +class RecursiveFieldSerializer(serializers.Serializer): + def to_representation(self, value): + serializer = self.parent.parent.__class__(value, context=self.context) + return serializer.data From bf301d21bb0e87ff9ac2973fd595a750ebf19431 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 02/18] Fix tests --- apps/location/serializers/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/location/serializers/common.py b/apps/location/serializers/common.py index 3d412ec6..374b4680 100644 --- a/apps/location/serializers/common.py +++ b/apps/location/serializers/common.py @@ -69,7 +69,7 @@ class CitySerializer(serializers.ModelSerializer): queryset=models.Country.objects.all(), write_only=True ) - country = CountrySerializer() + country = CountrySerializer(read_only=True) class Meta: model = models.City From 22521f76fcdd207256977934dc1a5af3ba14f688 Mon Sep 17 00:00:00 2001 From: "a.feteleu" Date: Tue, 12 Nov 2019 12:22:59 +0300 Subject: [PATCH 03/18] Change serializer field in ProductSerializer --- apps/product/serializers/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/product/serializers/common.py b/apps/product/serializers/common.py index 690aea99..2849bd26 100644 --- a/apps/product/serializers/common.py +++ b/apps/product/serializers/common.py @@ -76,7 +76,7 @@ class ProductBaseSerializer(serializers.ModelSerializer): subtypes = ProductSubTypeBaseSerializer(many=True) establishment = EstablishmentShortSerializer() tags = TagBaseSerializer(source='related_tags', many=True) - preview_image_url = serializers.ImageField(source='preview_main_image_url', allow_null=True) + preview_image_url = serializers.URLField(source='preview_main_image_url', allow_null=True) class Meta: """Meta class.""" From 706479060673cbfc5e22deaa197a43778f6be7f8 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Tue, 12 Nov 2019 12:41:27 +0300 Subject: [PATCH 04/18] added transfer for product notes --- .../migrations/0012_auto_20191112_0937.py | 36 +++++++++++++++++++ apps/product/models.py | 26 ++++++++++++-- apps/product/transfer_data.py | 29 ++++++++------- apps/transfer/management/commands/transfer.py | 2 +- apps/transfer/models.py | 2 +- apps/transfer/serializers/product.py | 24 +++++++++++++ 6 files changed, 99 insertions(+), 20 deletions(-) create mode 100644 apps/product/migrations/0012_auto_20191112_0937.py diff --git a/apps/product/migrations/0012_auto_20191112_0937.py b/apps/product/migrations/0012_auto_20191112_0937.py new file mode 100644 index 00000000..9df6a9bc --- /dev/null +++ b/apps/product/migrations/0012_auto_20191112_0937.py @@ -0,0 +1,36 @@ +# Generated by Django 2.2.7 on 2019-11-12 09:37 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('product', '0011_product_win_import_id'), + ] + + operations = [ + migrations.RemoveField( + model_name='product', + name='win_import_id', + ), + migrations.CreateModel( + name='ProductNote', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('text', models.TextField(verbose_name='text')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='notes', to='product.Product', verbose_name='product')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='notes', to=settings.AUTH_USER_MODEL, verbose_name='author')), + ], + options={ + 'verbose_name': 'product notes', + 'verbose_name_plural': 'product note', + }, + ), + ] diff --git a/apps/product/models.py b/apps/product/models.py index 6c037219..79cf5ded 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -193,9 +193,6 @@ class Product(TranslatedFieldsMixin, BaseAttributes): validators=[MinValueValidator(EARLIEST_VINTAGE_YEAR), MaxValueValidator(LATEST_VINTAGE_YEAR)]) gallery = models.ManyToManyField('gallery.Image', through='ProductGallery') - win_import_id = models.CharField(max_length=255, - blank=True, null=True, default=None, - help_text=_('attribute from legacy db')) reviews = generic.GenericRelation(to='review.Review') comments = generic.GenericRelation(to='comment.Comment') awards = generic.GenericRelation(to='main.Award', related_query_name='product') @@ -409,3 +406,26 @@ class ProductClassification(models.Model): """Meta class.""" verbose_name = _('product classification') verbose_name_plural = _('product classifications') + + +class ProductNoteQuerySet(models.QuerySet): + """QuerySet for model ProductNote.""" + + +class ProductNote(ProjectBaseMixin): + """Note model for Product entity.""" + text = models.TextField(verbose_name=_('text')) + product = models.ForeignKey(Product, on_delete=models.PROTECT, + related_name='notes', + verbose_name=_('product')) + user = models.ForeignKey('account.User', on_delete=models.PROTECT, + null=True, + related_name='notes', + verbose_name=_('author')) + + objects = ProductNoteQuerySet.as_manager() + + class Meta: + """Meta class.""" + verbose_name_plural = _('product note') + verbose_name = _('product notes') diff --git a/apps/product/transfer_data.py b/apps/product/transfer_data.py index 24d5c236..77e7cd89 100644 --- a/apps/product/transfer_data.py +++ b/apps/product/transfer_data.py @@ -113,18 +113,17 @@ def transfer_product(): pprint(f"transfer_product errors: {errors}") -def transfer_product_description(): - pass - # queryset = transfer_models.Products.objects.all() - # serialized_data = product_serializers.ProductSerializer( - # data=list(queryset.values()), - # many=True) - # if serialized_data.is_valid(): - # serialized_data.save() - # else: - # errors = [] - # for d in serialized_data.errors: errors.append(d) if d else None - # pprint(f"transfer_product errors: {errors}") +def transfer_product_note(): + queryset = transfer_models.ProductNotes.objects.exclude(text='') + serialized_data = product_serializers.ProductNoteSerializer( + data=list(queryset.values()), + many=True) + if serialized_data.is_valid(): + serialized_data.save() + else: + errors = [] + for d in serialized_data.errors: errors.append(d) if d else None + pprint(f"transfer_product_note errors: {errors}") def transfer_plate(): @@ -166,9 +165,9 @@ data_types = { "product": [ transfer_product, ], - # "product_description": [ - # transfer_product_description, - # ], + "product_note": [ + transfer_product_note, + ], "souvenir": [ transfer_plate, transfer_plate_image, diff --git a/apps/transfer/management/commands/transfer.py b/apps/transfer/management/commands/transfer.py index 58bf7807..d2cfaf41 100644 --- a/apps/transfer/management/commands/transfer.py +++ b/apps/transfer/management/commands/transfer.py @@ -32,7 +32,7 @@ class Command(BaseCommand): 'inquiries', # №6 - перенос запросов оценок 'wine_characteristics', 'product', - 'product_description', + 'product_note', 'souvenir', ] diff --git a/apps/transfer/models.py b/apps/transfer/models.py index 7f7dcc75..8b5ba081 100644 --- a/apps/transfer/models.py +++ b/apps/transfer/models.py @@ -973,7 +973,7 @@ class Products(MigrateMixin): class ProductNotes(MigrateMixin): using = 'legacy' - product_id = models.ForeignKey(Products, on_delete=models.DO_NOTHING) + product = models.ForeignKey(Products, on_delete=models.DO_NOTHING) text = models.CharField(max_length=255) win_import_id = models.CharField(max_length=255) diff --git a/apps/transfer/serializers/product.py b/apps/transfer/serializers/product.py index a9dab39a..0d6e938b 100644 --- a/apps/transfer/serializers/product.py +++ b/apps/transfer/serializers/product.py @@ -541,3 +541,27 @@ class PlateImageSerializer(serializers.ModelSerializer): product_qs = models.Product.objects.filter(old_id=product_id) if product_qs.exists(): return product_qs.first() + + +class ProductNoteSerializer(TransferSerializerMixin): + product_id = serializers.PrimaryKeyRelatedField( + queryset=transfer_models.Products.objects.all()) + text = serializers.CharField(allow_blank=True) + + class Meta: + model = models.ProductNote + fields = ( + 'product_id', + 'text', + ) + + def validate(self, attrs): + attrs['product'] = self.get_product(attrs.pop('product_id')) + return attrs + + def get_product(self, product): + if product: + old_id = product.id if hasattr(product, 'id') else product + qs = models.Product.objects.filter(old_id=old_id) + if qs.exists(): + return qs.first() From e065f1c9b4ae5e31251b3c2ffae35bd176cc052f Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 05/18] Works at weekday fiter --- apps/establishment/models.py | 5 +++++ apps/search_indexes/documents/establishment.py | 3 +++ apps/search_indexes/serializers.py | 1 + apps/search_indexes/views.py | 6 ++++++ 4 files changed, 15 insertions(+) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 75d3f6e9..048f45dd 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -461,6 +461,11 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): """ Used for indexing working by day """ return [ret.weekday for ret in self.schedule.all() if ret.works_at_noon] + @property + def works_at_weekday(self): + """ Used for indexing by working whole day criteria """ + return [ret.weekday for ret in self.schedule.all()] + @property def works_evening(self): """ Used for indexing working by day """ diff --git a/apps/search_indexes/documents/establishment.py b/apps/search_indexes/documents/establishment.py index 19d419aa..8db113c1 100644 --- a/apps/search_indexes/documents/establishment.py +++ b/apps/search_indexes/documents/establishment.py @@ -37,6 +37,9 @@ class EstablishmentDocument(Document): works_noon = fields.ListField(fields.IntegerField( attr='works_noon' )) + works_at_weekday = fields.ListField(fields.IntegerField( + attr='works_at_weekday' + )) works_now = fields.BooleanField(attr='works_now') tags = fields.ObjectField( properties={ diff --git a/apps/search_indexes/serializers.py b/apps/search_indexes/serializers.py index bbc61735..6aee06d0 100644 --- a/apps/search_indexes/serializers.py +++ b/apps/search_indexes/serializers.py @@ -108,6 +108,7 @@ class EstablishmentDocumentSerializer(DocumentSerializer): 'schedule', 'works_noon', 'works_evening', + 'works_at_weekday', # 'works_now', # 'collections', # 'establishment_type', diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 87b0ba64..92d96a64 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -156,6 +156,12 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet): constants.LOOKUP_QUERY_IN, ], }, + 'works_at_weekday': { + 'field': 'works_at_weekday', + 'lookups': [ + constants.LOOKUP_QUERY_IN, + ], + }, 'works_evening': { 'field': 'works_evening', 'lookups': [ From d3ab910fba2b9b61d8e6394818e95e605f084131 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 06/18] Filter recipes news --- apps/news/filters.py | 21 +++++++++++++++++---- apps/news/models.py | 6 ++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/apps/news/filters.py b/apps/news/filters.py index c4462189..084c570f 100644 --- a/apps/news/filters.py +++ b/apps/news/filters.py @@ -1,14 +1,21 @@ """Filters from application News""" -import django_filters +from django_filters import rest_framework as filters +from django.utils.translation import gettext_lazy as _ from news import models -class NewsListFilterSet(django_filters.FilterSet): +class NewsListFilterSet(filters.FilterSet): """FilterSet for News list""" - is_highlighted = django_filters.BooleanFilter() - title = django_filters.CharFilter(method='by_title') + is_highlighted = filters.BooleanFilter() + title = filters.CharFilter(method='by_title') + tag_group = filters.ChoiceFilter( + choices=( + (models.News.RECIPES_TAG_VALUE, _('Recipes')), + ), + method='by_tag_group' + ) class Meta: """Meta class""" @@ -16,8 +23,14 @@ class NewsListFilterSet(django_filters.FilterSet): fields = ( 'title', 'is_highlighted', + 'tag_group', ) + def by_tag_group(self, queryset, name, value): + if value == models.News.RECIPES_TAG_VALUE: + queryset = queryset.recipe_news() + return queryset + def by_title(self, queryset, name, value): """Crappy search by title according to locale""" if value: diff --git a/apps/news/models.py b/apps/news/models.py index 73a8c369..9cf385d2 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -53,6 +53,10 @@ class NewsQuerySet(TranslationQuerysetMixin): """Filter collection by country code.""" return self.filter(country__code=code) + def recipe_news(self): + """Returns news with tag 'cook' qs.""" + return self.filter(tags__value=News.RECIPES_TAG_VALUE) + def published(self): """Return only published news""" now = timezone.now() @@ -127,6 +131,8 @@ class News(BaseAttributes, TranslatedFieldsMixin): (PUBLISHED_EXCLUSIVE, _('Published exclusive')), ) + RECIPES_TAG_VALUE = 'cook' + old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None) news_type = models.ForeignKey(NewsType, on_delete=models.PROTECT, verbose_name=_('news type')) From 521d7f19f3f95c571867371375f7a6a4c4437910 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 07/18] Add city name field to establishment api representations --- apps/establishment/serializers/common.py | 14 +++++++++++++- apps/establishment/views/web.py | 2 +- apps/search_indexes/documents/establishment.py | 1 - apps/search_indexes/serializers.py | 9 +++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 268ffc82..23a21ad4 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -5,7 +5,7 @@ from rest_framework import serializers from comment import models as comment_models from comment.serializers import common as comment_serializers from establishment import models -from location.serializers import AddressBaseSerializer, CitySerializer +from location.serializers import AddressBaseSerializer, CitySerializer, AddressDetailSerializer from main.serializers import AwardSerializer, CurrencySerializer from tag.serializers import TagBaseSerializer from timetable.serialziers import ScheduleRUDSerializer @@ -225,6 +225,16 @@ class EstablishmentBaseSerializer(ProjectModelSerializer): 'currency' ] +class EstablishmentAddressExtendedSerializer(EstablishmentBaseSerializer): + """Establishment with city serializer.""" + + address = AddressDetailSerializer() + + class Meta(EstablishmentBaseSerializer.Meta): + """Meta class.""" + + fields = EstablishmentBaseSerializer.Meta.fields + class EstablishmentGeoSerializer(EstablishmentBaseSerializer): """Serializer for Geo view.""" @@ -260,6 +270,8 @@ class EstablishmentDetailSerializer(EstablishmentBaseSerializer): review = ReviewShortSerializer(source='last_published_review', allow_null=True) employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees', many=True) + address = AddressDetailSerializer(read_only=True) + menu = MenuSerializers(source='menu_set', many=True, read_only=True) best_price_menu = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True) best_price_carte = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True) diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index 8391315c..d11502f4 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -32,7 +32,7 @@ class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView): """Resource for getting a list of establishments.""" filter_class = filters.EstablishmentFilter - serializer_class = serializers.EstablishmentBaseSerializer + serializer_class = serializers.EstablishmentAddressExtendedSerializer class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView): diff --git a/apps/search_indexes/documents/establishment.py b/apps/search_indexes/documents/establishment.py index 19d419aa..fabfe88d 100644 --- a/apps/search_indexes/documents/establishment.py +++ b/apps/search_indexes/documents/establishment.py @@ -65,7 +65,6 @@ class EstablishmentDocument(Document): 'number': fields.IntegerField(), 'postal_code': fields.KeywordField(), 'coordinates': fields.GeoPointField(attr='location_field_indexing'), - # todo: remove if not used 'city': fields.ObjectField( properties={ 'id': fields.IntegerField(), diff --git a/apps/search_indexes/serializers.py b/apps/search_indexes/serializers.py index bbc61735..71f92caa 100644 --- a/apps/search_indexes/serializers.py +++ b/apps/search_indexes/serializers.py @@ -19,10 +19,19 @@ class TagsDocumentSerializer(serializers.Serializer): return get_translated_value(obj.label) +class CityDocumentShortSerializer(serializers.Serializer): + """City serializer for ES Document,""" + + id = serializers.IntegerField() + code = serializers.CharField(allow_null=True) + name = serializers.CharField() + + class AddressDocumentSerializer(serializers.Serializer): """Address serializer for ES Document.""" id = serializers.IntegerField() + city = CityDocumentShortSerializer() street_name_1 = serializers.CharField() street_name_2 = serializers.CharField() number = serializers.IntegerField() From 57a4498ba12f74a8ea5a966dd9ace6031f72bb42 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 08/18] Add schedule to establishment list serializer --- apps/establishment/models.py | 13 +++++++++++++ apps/establishment/serializers/common.py | 7 +++++-- apps/establishment/views/web.py | 6 +++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 75d3f6e9..8fe6dd43 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -111,6 +111,19 @@ class EstablishmentQuerySet(models.QuerySet): return self.select_related('address', 'establishment_type').\ prefetch_related('tags') + def with_schedule(self): + """Return qs with related schedule.""" + return self.prefetch_related('schedule') + + def with_currency_related(self): + """Return qs with related """ + return self.prefetch_related('currency') + + def with_extended_address_related(self): + """Return qs with deeply related address models.""" + return self.select_related('address__city', 'address__city__region', 'address__city__region__country', + 'address__city__country') + def with_extended_related(self): return self.select_related('establishment_type').\ prefetch_related('establishment_subtypes', 'awards', 'schedule', diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 23a21ad4..8784638a 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -225,15 +225,18 @@ class EstablishmentBaseSerializer(ProjectModelSerializer): 'currency' ] -class EstablishmentAddressExtendedSerializer(EstablishmentBaseSerializer): +class EstablishmentListRetrieveSerializer(EstablishmentBaseSerializer): """Establishment with city serializer.""" address = AddressDetailSerializer() + schedule = ScheduleRUDSerializer(many=True, allow_null=True) class Meta(EstablishmentBaseSerializer.Meta): """Meta class.""" - fields = EstablishmentBaseSerializer.Meta.fields + fields = EstablishmentBaseSerializer.Meta.fields + [ + 'schedule', + ] class EstablishmentGeoSerializer(EstablishmentBaseSerializer): diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index d11502f4..2a6fd215 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -32,7 +32,11 @@ class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView): """Resource for getting a list of establishments.""" filter_class = filters.EstablishmentFilter - serializer_class = serializers.EstablishmentAddressExtendedSerializer + serializer_class = serializers.EstablishmentListRetrieveSerializer + + def get_queryset(self): + return super().get_queryset().with_schedule()\ + .with_extended_address_related().with_currency_related() class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView): From 7d4d555eee16700505a5c931d854ee9a7dfc821f Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 09/18] Label translated field is translated again --- apps/tag/serializers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/tag/serializers.py b/apps/tag/serializers.py index 8416ffcd..d6b851ab 100644 --- a/apps/tag/serializers.py +++ b/apps/tag/serializers.py @@ -42,9 +42,7 @@ class TagBackOfficeSerializer(TagBaseSerializer): class TagCategoryBaseSerializer(serializers.ModelSerializer): """Serializer for model TagCategory.""" - # todo: refactor this - # label_translated = TranslatedField() - label_translated = serializers.CharField(source='index_name', read_only=True, allow_null=True) + label_translated = TranslatedField() tags = TagBaseSerializer(many=True, read_only=True) class Meta: From 7bba5237dc34d0aa8b6046423cd36ef62ee46ea2 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 10/18] Closed_at fill command --- .../management/commands/add_closed_at_timetable.py | 14 ++++++++++++++ apps/timetable/transfer.py | 1 + 2 files changed, 15 insertions(+) create mode 100644 apps/establishment/management/commands/add_closed_at_timetable.py diff --git a/apps/establishment/management/commands/add_closed_at_timetable.py b/apps/establishment/management/commands/add_closed_at_timetable.py new file mode 100644 index 00000000..d7b80d61 --- /dev/null +++ b/apps/establishment/management/commands/add_closed_at_timetable.py @@ -0,0 +1,14 @@ +from django.core.management.base import BaseCommand +from timetable.models import Timetable + +class Command(BaseCommand): + help = '''Add closed_at, opening_at Timetable fields''' + + def handle(self, *args, **options): + for tt in Timetable.objects.all(): + end = tt.dinner_end or tt.lunch_end + start = tt.lunch_start or tt.dinner_start + if end or start: + tt.closed_at = end + tt.opening_at = start + tt.save() \ No newline at end of file diff --git a/apps/timetable/transfer.py b/apps/timetable/transfer.py index 915b9ad5..2b8fa45f 100644 --- a/apps/timetable/transfer.py +++ b/apps/timetable/transfer.py @@ -66,6 +66,7 @@ card = { "fields": { "Schedules": { # нет аналогов для weekday, opening_at, closed_at + # upd: запустить команду add_closed_at_timetable. она заполнит opening_at, closed_at "lunch_start": "lunch_start", "lunch_end": "lunch_end", "diner_start": "diner_start", From 8eac730d9f924e02d0032da18ffda8d6a3495862 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Tue, 12 Nov 2019 15:14:35 +0300 Subject: [PATCH 11/18] added transfer for notes --- .../migrations/0059_establishmentnote.py | 33 +++++++++++++ apps/establishment/models.py | 24 +++++++++ apps/establishment/transfer_data.py | 21 +++++++- ...112_0937.py => 0012_auto_20191112_1007.py} | 7 +-- apps/product/models.py | 5 +- apps/product/transfer_data.py | 8 +-- apps/transfer/management/commands/transfer.py | 1 + apps/transfer/models.py | 14 +++++- apps/transfer/serializers/establishment.py | 49 +++++++++++++++++-- apps/transfer/serializers/product.py | 21 +++++--- 10 files changed, 162 insertions(+), 21 deletions(-) create mode 100644 apps/establishment/migrations/0059_establishmentnote.py rename apps/product/migrations/{0012_auto_20191112_0937.py => 0012_auto_20191112_1007.py} (78%) diff --git a/apps/establishment/migrations/0059_establishmentnote.py b/apps/establishment/migrations/0059_establishmentnote.py new file mode 100644 index 00000000..5b55f701 --- /dev/null +++ b/apps/establishment/migrations/0059_establishmentnote.py @@ -0,0 +1,33 @@ +# Generated by Django 2.2.7 on 2019-11-12 10:07 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('establishment', '0058_merge_20191106_0921'), + ] + + operations = [ + migrations.CreateModel( + name='EstablishmentNote', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('old_id', models.PositiveIntegerField(blank=True, null=True)), + ('text', models.TextField(verbose_name='text')), + ('establishment', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='establishment_notes', to='establishment.Establishment', verbose_name='establishment')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='establishment_notes', to=settings.AUTH_USER_MODEL, verbose_name='author')), + ], + options={ + 'verbose_name': 'product notes', + 'verbose_name_plural': 'product note', + }, + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 75d3f6e9..ef3630c4 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -520,6 +520,30 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): return self.products.wines() +class EstablishmentNoteQuerySet(models.QuerySet): + """QuerySet for model EstablishmentNote.""" + + +class EstablishmentNote(ProjectBaseMixin): + """Note model for Establishment entity.""" + old_id = models.PositiveIntegerField(null=True, blank=True) + text = models.TextField(verbose_name=_('text')) + establishment = models.ForeignKey(Establishment, on_delete=models.PROTECT, + related_name='establishment_notes', + verbose_name=_('establishment')) + user = models.ForeignKey('account.User', on_delete=models.PROTECT, + null=True, + related_name='establishment_notes', + verbose_name=_('author')) + + objects = EstablishmentNoteQuerySet.as_manager() + + class Meta: + """Meta class.""" + verbose_name_plural = _('product note') + verbose_name = _('product notes') + + class Position(BaseAttributes, TranslatedFieldsMixin): """Position model.""" diff --git a/apps/establishment/transfer_data.py b/apps/establishment/transfer_data.py index d0042519..b3dc58f9 100644 --- a/apps/establishment/transfer_data.py +++ b/apps/establishment/transfer_data.py @@ -4,8 +4,9 @@ from django.db.models import Q, F from establishment.models import Establishment from location.models import Address -from transfer.models import Establishments, Dishes -from transfer.serializers.establishment import EstablishmentSerializer +from transfer.models import Establishments, Dishes, EstablishmentNotes +from transfer.serializers.establishment import EstablishmentSerializer, \ + EstablishmentNoteSerializer from transfer.serializers.plate import PlateSerializer @@ -124,10 +125,26 @@ def transfer_establishment_addresses(): establishment.save() +def transfer_establishment_note(): + errors = [] + queryset = EstablishmentNotes.objects.exclude(text__exact='') \ + .exclude(text__isnull=True) \ + .exclude(establishment_id__isnull=True) + serialized_data = EstablishmentNoteSerializer( + data=list(queryset.values()), + many=True) + if serialized_data.is_valid(): + serialized_data.save() + else: + for d in serialized_data.errors: errors.append(d) if d else None + pprint(f"transfer_establishment_note errors: {errors}") + + data_types = { "establishment": [ transfer_establishment, ], + "establishment_note": [transfer_establishment_note], "location_establishment": [ transfer_establishment_addresses ], diff --git a/apps/product/migrations/0012_auto_20191112_0937.py b/apps/product/migrations/0012_auto_20191112_1007.py similarity index 78% rename from apps/product/migrations/0012_auto_20191112_0937.py rename to apps/product/migrations/0012_auto_20191112_1007.py index 9df6a9bc..66d61bc5 100644 --- a/apps/product/migrations/0012_auto_20191112_0937.py +++ b/apps/product/migrations/0012_auto_20191112_1007.py @@ -1,4 +1,4 @@ -# Generated by Django 2.2.7 on 2019-11-12 09:37 +# Generated by Django 2.2.7 on 2019-11-12 10:07 from django.conf import settings from django.db import migrations, models @@ -24,9 +24,10 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('old_id', models.PositiveIntegerField(blank=True, null=True)), ('text', models.TextField(verbose_name='text')), - ('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='notes', to='product.Product', verbose_name='product')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='notes', to=settings.AUTH_USER_MODEL, verbose_name='author')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='product_notes', to='product.Product', verbose_name='product')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='product_notes', to=settings.AUTH_USER_MODEL, verbose_name='author')), ], options={ 'verbose_name': 'product notes', diff --git a/apps/product/models.py b/apps/product/models.py index 79cf5ded..2f964627 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -414,13 +414,14 @@ class ProductNoteQuerySet(models.QuerySet): class ProductNote(ProjectBaseMixin): """Note model for Product entity.""" + old_id = models.PositiveIntegerField(null=True, blank=True) text = models.TextField(verbose_name=_('text')) product = models.ForeignKey(Product, on_delete=models.PROTECT, - related_name='notes', + related_name='product_notes', verbose_name=_('product')) user = models.ForeignKey('account.User', on_delete=models.PROTECT, null=True, - related_name='notes', + related_name='product_notes', verbose_name=_('author')) objects = ProductNoteQuerySet.as_manager() diff --git a/apps/product/transfer_data.py b/apps/product/transfer_data.py index 77e7cd89..8e4a26fa 100644 --- a/apps/product/transfer_data.py +++ b/apps/product/transfer_data.py @@ -101,6 +101,7 @@ def transfer_wine_classifications(): def transfer_product(): + errors = [] queryset = transfer_models.Products.objects.all() serialized_data = product_serializers.ProductSerializer( data=list(queryset.values()), @@ -108,12 +109,12 @@ def transfer_product(): if serialized_data.is_valid(): serialized_data.save() else: - errors = [] for d in serialized_data.errors: errors.append(d) if d else None pprint(f"transfer_product errors: {errors}") def transfer_product_note(): + errors = [] queryset = transfer_models.ProductNotes.objects.exclude(text='') serialized_data = product_serializers.ProductNoteSerializer( data=list(queryset.values()), @@ -121,12 +122,12 @@ def transfer_product_note(): if serialized_data.is_valid(): serialized_data.save() else: - errors = [] for d in serialized_data.errors: errors.append(d) if d else None pprint(f"transfer_product_note errors: {errors}") def transfer_plate(): + errors = [] queryset = transfer_models.Merchandise.objects.all() serialized_data = product_serializers.PlateSerializer( data=list(queryset.values()), @@ -134,12 +135,12 @@ def transfer_plate(): if serialized_data.is_valid(): serialized_data.save() else: - errors = [] for d in serialized_data.errors: errors.append(d) if d else None pprint(f"transfer_plates errors: {errors}") def transfer_plate_image(): + errors = [] queryset = transfer_models.Merchandise.objects.all() serialized_data = product_serializers.PlateImageSerializer( data=list(queryset.values()), @@ -147,7 +148,6 @@ def transfer_plate_image(): if serialized_data.is_valid(): serialized_data.save() else: - errors = [] for d in serialized_data.errors: errors.append(d) if d else None pprint(f"transfer_plates_images errors: {errors}") diff --git a/apps/transfer/management/commands/transfer.py b/apps/transfer/management/commands/transfer.py index d2cfaf41..7f0b5f4b 100644 --- a/apps/transfer/management/commands/transfer.py +++ b/apps/transfer/management/commands/transfer.py @@ -34,6 +34,7 @@ class Command(BaseCommand): 'product', 'product_note', 'souvenir', + 'establishment_note', ] def handle(self, *args, **options): diff --git a/apps/transfer/models.py b/apps/transfer/models.py index 8b5ba081..2c7fe726 100644 --- a/apps/transfer/models.py +++ b/apps/transfer/models.py @@ -447,6 +447,18 @@ class Establishments(MigrateMixin): db_table = 'establishments' +class EstablishmentNotes(MigrateMixin): + using = 'legacy' + + establishment_id = models.IntegerField(null=True, blank=True) + account_id = models.IntegerField(null=True, blank=True) + text = models.TextField(null=True) + + class Meta: + managed = False + db_table = 'notes' + + class Descriptions(MigrateMixin): using = 'legacy' @@ -973,7 +985,7 @@ class Products(MigrateMixin): class ProductNotes(MigrateMixin): using = 'legacy' - product = models.ForeignKey(Products, on_delete=models.DO_NOTHING) + product_id = models.IntegerField(null=True, blank=True) text = models.CharField(max_length=255) win_import_id = models.CharField(max_length=255) diff --git a/apps/transfer/serializers/establishment.py b/apps/transfer/serializers/establishment.py index f9127d6e..0e5f55d4 100644 --- a/apps/transfer/serializers/establishment.py +++ b/apps/transfer/serializers/establishment.py @@ -1,16 +1,17 @@ from django.conf import settings from django.core.exceptions import MultipleObjectsReturned, ValidationError from django.db import transaction +from django.utils.text import slugify from rest_framework import serializers -from establishment.models import Establishment, ContactEmail, ContactPhone, EstablishmentType, \ - EstablishmentSubType +from account.models import User +from establishment.models import Establishment, ContactEmail, ContactPhone, \ + EstablishmentType, EstablishmentSubType, EstablishmentNote from location.models import Address from timetable.models import Timetable from utils.legacy_parser import parse_legacy_schedule_content from utils.serializers import TimeZoneChoiceField from utils.slug_generator import generate_unique_slug -from django.utils.text import slugify class EstablishmentSerializer(serializers.ModelSerializer): @@ -173,3 +174,45 @@ class EstablishmentSerializer(serializers.ModelSerializer): index_name=slugify(subtype_name), establishment_type_id=establishment_type_id) return subtype + + +class EstablishmentNoteSerializer(serializers.ModelSerializer): + + id = serializers.IntegerField() + establishment_id = serializers.IntegerField() + account_id = serializers.IntegerField(allow_null=True) + text = serializers.CharField(allow_blank=True, allow_null=True) + + class Meta: + model = EstablishmentNote + fields = ( + 'id', + 'establishment_id', + 'account_id', + 'text', + ) + + def validate(self, attrs): + attrs['old_id'] = attrs['id'] + attrs['establishment'] = self.get_establishment(attrs.pop('establishment_id')) + attrs['user'] = self.get_user(attrs.pop('account_id')) + return attrs + + def create(self, validated_data): + qs = self.Meta.model.objects.filter(**validated_data) + establishment = validated_data.get('establishment') + + if not qs.exists() and establishment: + obj = super().create(validated_data) + return obj + + def get_establishment(self, old_id): + if old_id: + qs = Establishment.objects.filter(old_id=old_id) + if qs.exists(): + return qs.first() + + def get_user(self, old_id): + qs = User.objects.exclude(old_id__isnull=True).filter(old_id=old_id) + if qs.exists(): + return qs.first() diff --git a/apps/transfer/serializers/product.py b/apps/transfer/serializers/product.py index 0d6e938b..75508677 100644 --- a/apps/transfer/serializers/product.py +++ b/apps/transfer/serializers/product.py @@ -543,25 +543,34 @@ class PlateImageSerializer(serializers.ModelSerializer): return product_qs.first() -class ProductNoteSerializer(TransferSerializerMixin): - product_id = serializers.PrimaryKeyRelatedField( - queryset=transfer_models.Products.objects.all()) +class ProductNoteSerializer(serializers.ModelSerializer): + + id = serializers.IntegerField() + product_id = serializers.IntegerField() text = serializers.CharField(allow_blank=True) class Meta: model = models.ProductNote fields = ( + 'id', 'product_id', 'text', ) def validate(self, attrs): + attrs['old_id'] = attrs['id'] attrs['product'] = self.get_product(attrs.pop('product_id')) return attrs - def get_product(self, product): - if product: - old_id = product.id if hasattr(product, 'id') else product + def create(self, validated_data): + qs = self.Meta.model.objects.filter(**validated_data) + product = validated_data.get('product') + + if not qs.exists() and product: + return super().create(validated_data) + + def get_product(self, old_id): + if old_id: qs = models.Product.objects.filter(old_id=old_id) if qs.exists(): return qs.first() From 0af5de9bd40f92268992a86779e52adb242ad893 Mon Sep 17 00:00:00 2001 From: "a.feteleu" Date: Tue, 12 Nov 2019 15:18:46 +0300 Subject: [PATCH 12/18] added merge migration --- apps/main/migrations/0035_merge_20191112_1218.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 apps/main/migrations/0035_merge_20191112_1218.py diff --git a/apps/main/migrations/0035_merge_20191112_1218.py b/apps/main/migrations/0035_merge_20191112_1218.py new file mode 100644 index 00000000..2f25a46f --- /dev/null +++ b/apps/main/migrations/0035_merge_20191112_1218.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.7 on 2019-11-12 12:18 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0034_sitefeature_nested'), + ('main', '0034_auto_20191112_0104'), + ] + + operations = [ + ] From a7f9bfd1613d2662ac090e2b7c421420fd1f16fe Mon Sep 17 00:00:00 2001 From: Semyon Yekhmenin Date: Tue, 12 Nov 2019 13:10:12 +0000 Subject: [PATCH 13/18] Feature/news search translation fix --- apps/search_indexes/utils.py | 221 ++++++++++++++++++++++++++++++++++- 1 file changed, 218 insertions(+), 3 deletions(-) diff --git a/apps/search_indexes/utils.py b/apps/search_indexes/utils.py index d6153da2..c91b9e4a 100644 --- a/apps/search_indexes/utils.py +++ b/apps/search_indexes/utils.py @@ -2,13 +2,226 @@ from django_elasticsearch_dsl import fields from utils.models import get_current_locale, get_default_locale +ALL_LOCALES_LIST = [ + 'af-ZA', + 'am-ET', + 'ar-AE', + 'ar-BH', + 'ar-DZ', + 'ar-EG', + 'ar-IQ', + 'ar-JO', + 'ar-KW', + 'ar-LB', + 'ar-LY', + 'ar-MA', + 'arn-CL', + 'ar-OM', + 'ar-QA', + 'ar-SA', + 'ar-SY', + 'ar-TN', + 'ar-YE', + 'as-IN', + 'az-Cyrl-AZ', + 'az-Latn-AZ', + 'ba-RU', + 'be-BY', + 'bg-BG', + 'bn-BD', + 'bn-IN', + 'bo-CN', + 'br-FR', + 'bs-Cyrl-BA', + 'bs-Latn-BA', + 'ca-ES', + 'co-FR', + 'cs-CZ', + 'cy-GB', + 'da-DK', + 'de-AT', + 'de-CH', + 'de-DE', + 'de-LI', + 'de-LU', + 'dsb-DE', + 'dv-MV', + 'el-GR', + 'en-029', + 'en-AU', + 'en-BZ', + 'en-CA', + 'en-GB', + 'en-IE', + 'en-IN', + 'en-JM', + 'en-MY', + 'en-NZ', + 'en-PH', + 'en-SG', + 'en-TT', + 'en-US', + 'en-ZA', + 'en-ZW', + 'es-AR', + 'es-BO', + 'es-CL', + 'es-CO', + 'es-CR', + 'es-DO', + 'es-EC', + 'es-ES', + 'es-GT', + 'es-HN', + 'es-MX', + 'es-NI', + 'es-PA', + 'es-PE', + 'es-PR', + 'es-PY', + 'es-SV', + 'es-US', + 'es-UY', + 'es-VE', + 'et-EE', + 'eu-ES', + 'fa-IR', + 'fi-FI', + 'fil-PH', + 'fo-FO', + 'fr-BE', + 'fr-CA', + 'fr-CH', + 'fr-FR', + 'fr-LU', + 'fr-MC', + 'fy-NL', + 'ga-IE', + 'gd-GB', + 'gl-ES', + 'gsw-FR', + 'gu-IN', + 'ha-Latn-NG', + 'he-IL', + 'hi-IN', + 'hr-BA', + 'hr-HR', + 'hsb-DE', + 'hu-HU', + 'hy-AM', + 'id-ID', + 'ig-NG', + 'ii-CN', + 'is-IS', + 'it-CH', + 'it-IT', + 'iu-Cans-CA', + 'iu-Latn-CA', + 'ja-JP', + 'ka-GE', + 'kk-KZ', + 'kl-GL', + 'km-KH', + 'kn-IN', + 'kok-IN', + 'ko-KR', + 'ky-KG', + 'lb-LU', + 'lo-LA', + 'lt-LT', + 'lv-LV', + 'mi-NZ', + 'mk-MK', + 'ml-IN', + 'mn-MN', + 'mn-Mong-CN', + 'moh-CA', + 'mr-IN', + 'ms-BN', + 'ms-MY', + 'mt-MT', + 'nb-NO', + 'ne-NP', + 'nl-BE', + 'nl-NL', + 'nn-NO', + 'nso-ZA', + 'oc-FR', + 'or-IN', + 'pa-IN', + 'pl-PL', + 'prs-AF', + 'ps-AF', + 'pt-BR', + 'pt-PT', + 'qut-GT', + 'quz-BO', + 'quz-EC', + 'quz-PE', + 'rm-CH', + 'ro-RO', + 'ru-RU', + 'rw-RW', + 'sah-RU', + 'sa-IN', + 'se-FI', + 'se-NO', + 'se-SE', + 'si-LK', + 'sk-SK', + 'sl-SI', + 'sma-NO', + 'sma-SE', + 'smj-NO', + 'smj-SE', + 'smn-FI', + 'sms-FI', + 'sq-AL', + 'sr-Cyrl-BA', + 'sr-Cyrl-CS', + 'sr-Cyrl-ME', + 'sr-Cyrl-RS', + 'sr-Latn-BA', + 'sr-Latn-CS', + 'sr-Latn-ME', + 'sr-Latn-RS', + 'sv-FI', + 'sv-SE', + 'sw-KE', + 'syr-SY', + 'ta-IN', + 'te-IN', + 'tg-Cyrl-TJ', + 'th-TH', + 'tk-TM', + 'tn-ZA', + 'tr-TR', + 'tt-RU', + 'tzm-Latn-DZ', + 'ug-CN', + 'uk-UA', + 'ur-PK', + 'uz-Cyrl-UZ', + 'uz-Latn-UZ', + 'vi-VN', + 'wo-SN', + 'xh-ZA', + 'yo-NG', + 'zh-CN', + 'zh-HK', + 'zh-MO', + 'zh-SG', + 'zh-TW', + 'zu-ZA', +] # object field properties -OBJECT_FIELD_PROPERTIES = { +OBJECT_FIELD_PROPERTIES = {locale: fields.TextField() for locale in ALL_LOCALES_LIST} +OBJECT_FIELD_PROPERTIES.update({ 'en-GB': fields.TextField(analyzer='english'), 'ru-RU': fields.TextField(analyzer='russian'), - 'fr-FR': fields.TextField(analyzer='french'), -} + 'fr-FR': fields.TextField(analyzer='french') +}) # todo: refactor serializer @@ -23,4 +236,6 @@ def get_translated_value(value): # fallback if value is None: value = field_dict.get(get_default_locale()) + if value is None: + value = field_dict.get(next(iter(field_dict.keys()), None)) return value From fe6f9953d8aa1a1b4b40d2663a9ef3a63521ee4b Mon Sep 17 00:00:00 2001 From: Semyon Yekhmenin Date: Tue, 12 Nov 2019 13:12:10 +0000 Subject: [PATCH 14/18] Added mobile news endpoints --- apps/news/urls/common.py | 9 +++++++++ apps/news/urls/mobile.py | 8 ++++++++ apps/news/urls/web.py | 12 ++++-------- project/urls/mobile.py | 2 +- 4 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 apps/news/urls/common.py create mode 100644 apps/news/urls/mobile.py diff --git a/apps/news/urls/common.py b/apps/news/urls/common.py new file mode 100644 index 00000000..b42905eb --- /dev/null +++ b/apps/news/urls/common.py @@ -0,0 +1,9 @@ +from django.urls import path +from news import views + +common_urlpatterns = [ + path('', views.NewsListView.as_view(), name='list'), + path('types/', views.NewsTypeListView.as_view(), name='type'), + path('slug//', views.NewsDetailView.as_view(), name='rud'), + path('slug//favorites/', views.NewsFavoritesCreateDestroyView.as_view(), name='create-destroy-favorites') +] diff --git a/apps/news/urls/mobile.py b/apps/news/urls/mobile.py new file mode 100644 index 00000000..680e3ecc --- /dev/null +++ b/apps/news/urls/mobile.py @@ -0,0 +1,8 @@ +"""News app urlconf.""" +from news.urls.common import common_urlpatterns + +app_name = 'news' + +urlpatterns = [] + +urlpatterns.extend(common_urlpatterns) diff --git a/apps/news/urls/web.py b/apps/news/urls/web.py index fdfe8a66..680e3ecc 100644 --- a/apps/news/urls/web.py +++ b/apps/news/urls/web.py @@ -1,12 +1,8 @@ """News app urlconf.""" -from django.urls import path -from news import views +from news.urls.common import common_urlpatterns app_name = 'news' -urlpatterns = [ - path('', views.NewsListView.as_view(), name='list'), - path('types/', views.NewsTypeListView.as_view(), name='type'), - path('slug//', views.NewsDetailView.as_view(), name='rud'), - path('slug//favorites/', views.NewsFavoritesCreateDestroyView.as_view(), name='create-destroy-favorites') -] +urlpatterns = [] + +urlpatterns.extend(common_urlpatterns) diff --git a/project/urls/mobile.py b/project/urls/mobile.py index 4ec2fec5..8a1558bc 100644 --- a/project/urls/mobile.py +++ b/project/urls/mobile.py @@ -12,6 +12,6 @@ urlpatterns = [ # path('advertisement/', include('advertisement.urls.web')), # path('collection/', include('collection.urls.web')), # path('establishments/', include('establishment.urls.web')), - # path('news/', include('news.urls.web')), + path('news/', include('news.urls.mobile')), # path('partner/', include('partner.urls.web')), ] From 0db7972b5a9735752d33feee429240686e71d521 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 12 Nov 2019 16:19:03 +0300 Subject: [PATCH 15/18] fix comment country --- apps/comment/admin.py | 2 +- .../migrations/0005_remove_comment_country.py | 17 +++++++++++++++++ apps/comment/models.py | 4 +--- apps/comment/transfer_data.py | 1 - apps/transfer/serializers/comments.py | 14 +------------- 5 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 apps/comment/migrations/0005_remove_comment_country.py diff --git a/apps/comment/admin.py b/apps/comment/admin.py index 061c9c8d..d3dfe2e3 100644 --- a/apps/comment/admin.py +++ b/apps/comment/admin.py @@ -6,4 +6,4 @@ from . import models @admin.register(models.Comment) class CommentModelAdmin(admin.ModelAdmin): """Model admin for model Comment""" - raw_id_fields = ('user', 'country') + raw_id_fields = ('user',) diff --git a/apps/comment/migrations/0005_remove_comment_country.py b/apps/comment/migrations/0005_remove_comment_country.py new file mode 100644 index 00000000..d0688a2f --- /dev/null +++ b/apps/comment/migrations/0005_remove_comment_country.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.7 on 2019-11-12 13:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('comment', '0004_comment_old_id'), + ] + + operations = [ + migrations.RemoveField( + model_name='comment', + name='country', + ), + ] diff --git a/apps/comment/models.py b/apps/comment/models.py index 3a8c8c37..9bf93697 100644 --- a/apps/comment/models.py +++ b/apps/comment/models.py @@ -4,10 +4,9 @@ from django.db import models from django.utils.translation import gettext_lazy as _ from account.models import User +from translation.models import Language from utils.models import ProjectBaseMixin from utils.querysets import ContentTypeQuerySetMixin -from translation.models import Language -from location.models import Country class CommentQuerySet(ContentTypeQuerySetMixin): @@ -34,7 +33,6 @@ class Comment(ProjectBaseMixin): text = models.TextField(verbose_name=_('Comment text')) mark = models.PositiveIntegerField(blank=True, null=True, default=None, verbose_name=_('Mark')) user = models.ForeignKey('account.User', related_name='comments', on_delete=models.CASCADE, verbose_name=_('User')) - country = models.ForeignKey(Country, verbose_name=_('Country'), on_delete=models.SET_NULL, null=True) old_id = models.IntegerField(null=True, blank=True, default=None) content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE) diff --git a/apps/comment/transfer_data.py b/apps/comment/transfer_data.py index 843da78f..679fbfb8 100644 --- a/apps/comment/transfer_data.py +++ b/apps/comment/transfer_data.py @@ -22,7 +22,6 @@ def transfer_comments(): 'id', 'comment', 'mark', - 'locale', 'establishment_id', 'account_id', ) diff --git a/apps/transfer/serializers/comments.py b/apps/transfer/serializers/comments.py index cd4233d1..fe75093a 100644 --- a/apps/transfer/serializers/comments.py +++ b/apps/transfer/serializers/comments.py @@ -1,14 +1,13 @@ from rest_framework import serializers + from comment.models import Comment, User from establishment.models import Establishment -from location.models import Country class CommentSerializer(serializers.Serializer): id = serializers.IntegerField() comment = serializers.CharField() mark = serializers.DecimalField(max_digits=4, decimal_places=2) - locale = serializers.CharField() account_id = serializers.IntegerField() establishment_id = serializers.CharField() @@ -19,11 +18,9 @@ class CommentSerializer(serializers.Serializer): 'mark': data['mark'] * -1 if data['mark'] < 0 else data['mark'], 'content_object': self.get_content_object(data), 'user': self.get_account(data), - 'country': self.get_country(data), }) data.pop('establishment_id') data.pop('account_id') - data.pop('locale') return data def create(self, validated_data): @@ -45,12 +42,3 @@ class CommentSerializer(serializers.Serializer): if not user: raise ValueError(f"User account not found with old_id {data['account_id']}") return user - - @staticmethod - def get_country(data): - locale = data['locale'] - country_code = locale[:locale.index("-")] if len(locale) > 2 else locale - country = Country.objects.filter(code=country_code).first() - if not country: - raise ValueError(f"Country not found with code {country_code}") - return country From 3f2de46420e582cb00755faff3b9640659439639 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 12 Nov 2019 16:38:06 +0300 Subject: [PATCH 16/18] fix filter comment by establishment and user --- apps/comment/transfer_data.py | 18 +++++++----------- apps/transfer/serializers/comments.py | 10 ++++++++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/comment/transfer_data.py b/apps/comment/transfer_data.py index 679fbfb8..c9d07585 100644 --- a/apps/comment/transfer_data.py +++ b/apps/comment/transfer_data.py @@ -1,8 +1,7 @@ from pprint import pprint -from django.db.models import Q - -from account.transfer_data import STOP_LIST +from account.models import User +from establishment.models import Establishment from transfer.models import Comments from transfer.serializers.comments import CommentSerializer @@ -10,14 +9,11 @@ from transfer.serializers.comments import CommentSerializer def transfer_comments(): # В queryset исключены объекты по условию в связанные моделях # см. transfer_establishment() и transfer_user() - queryset = Comments.objects.exclude( - Q(establishment__type='Wineyard') | - Q(establishment__location__timezone__isnull=True) | - Q(account__confirmed_at__isnull=True) | - Q(account__email__in=STOP_LIST) - ).filter( - account__isnull=False, - mark__isnull=False + establishments = Establishment.objects.all().values_list('old_id', flat=True) + users = User.objects.all().values_list('old_id', flat=True) + queryset = Comments.objects.filter( + establishment_id__in=list(establishments), + account_id__in=list(users), ).only( 'id', 'comment', diff --git a/apps/transfer/serializers/comments.py b/apps/transfer/serializers/comments.py index fe75093a..73c90802 100644 --- a/apps/transfer/serializers/comments.py +++ b/apps/transfer/serializers/comments.py @@ -7,7 +7,7 @@ from establishment.models import Establishment class CommentSerializer(serializers.Serializer): id = serializers.IntegerField() comment = serializers.CharField() - mark = serializers.DecimalField(max_digits=4, decimal_places=2) + mark = serializers.DecimalField(max_digits=4, decimal_places=2, allow_null=True) account_id = serializers.IntegerField() establishment_id = serializers.CharField() @@ -15,7 +15,7 @@ class CommentSerializer(serializers.Serializer): data.update({ 'old_id': data.pop('id'), 'text': data.pop('comment'), - 'mark': data['mark'] * -1 if data['mark'] < 0 else data['mark'], + 'mark': self.get_mark(data), 'content_object': self.get_content_object(data), 'user': self.get_account(data), }) @@ -42,3 +42,9 @@ class CommentSerializer(serializers.Serializer): if not user: raise ValueError(f"User account not found with old_id {data['account_id']}") return user + + @staticmethod + def get_mark(data): + if not data['mark']: + return None + return data['mark'] * -1 if data['mark'] < 0 else data['mark'] From 1d2440ff7b446834432cf03cb22931c2a84dada8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Tue, 12 Nov 2019 17:02:05 +0300 Subject: [PATCH 17/18] fix TagCategory label migrator --- apps/tag/management/commands/add_tags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tag/management/commands/add_tags.py b/apps/tag/management/commands/add_tags.py index d905816c..37fdbbea 100644 --- a/apps/tag/management/commands/add_tags.py +++ b/apps/tag/management/commands/add_tags.py @@ -46,7 +46,7 @@ class Command(BaseCommand): 'en-GB': key_value.key_name, 'fr-FR': key_value.key_name, 'ru-RU': key_value.key_name, - }, + } tag_category.value_type = key_value.value_type tag_category.save() est_type.tag_categories.add( From 621918af4a56e16269a8b4af529e6e6020ed92c5 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 12 Nov 2019 17:07:58 +0300 Subject: [PATCH 18/18] Fixed last fallback translation case --- apps/search_indexes/utils.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/apps/search_indexes/utils.py b/apps/search_indexes/utils.py index c91b9e4a..b88a1da3 100644 --- a/apps/search_indexes/utils.py +++ b/apps/search_indexes/utils.py @@ -230,12 +230,14 @@ def get_translated_value(value): return None elif not isinstance(value, dict): field_dict = value.to_dict() - elif isinstance(value, dict): + else: field_dict = value - value = field_dict.get(get_current_locale()) + field_dict = {k: v for k, v in field_dict.items() if v is not None} + result = field_dict.get(get_current_locale(), None) # fallback - if value is None: - value = field_dict.get(get_default_locale()) - if value is None: - value = field_dict.get(next(iter(field_dict.keys()), None)) - return value + if result is None: + result = field_dict.get(get_default_locale(), None) + if result is None: + values = list(field_dict.values()) + result = values[0] if values else None + return result