From c2e111f75b0e72e6ed398009c8c452f69720446a Mon Sep 17 00:00:00 2001 From: littlewolf Date: Wed, 27 Nov 2019 18:12:22 +0300 Subject: [PATCH 1/8] Fix queryset --- apps/partner/views/common.py | 2 +- docker-compose.mysql.yml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/partner/views/common.py b/apps/partner/views/common.py index a5d0338c..3c45fb6b 100644 --- a/apps/partner/views/common.py +++ b/apps/partner/views/common.py @@ -8,7 +8,7 @@ from partner.serializers import common as serializers # Mixins class PartnerViewMixin(generics.GenericAPIView): """View mixin for Partner views""" - queryset = models.Partner.objects.all() + queryset = models.Partner.objects.distinct("name") # Views diff --git a/docker-compose.mysql.yml b/docker-compose.mysql.yml index bd81ecb2..106cabb3 100644 --- a/docker-compose.mysql.yml +++ b/docker-compose.mysql.yml @@ -13,6 +13,9 @@ services: MYSQL_ROOT_PASSWORD: rootPassword volumes: - gm-mysql_db:/var/lib/mysql + - .:/code + + # PostgreSQL database From 1372538acf7e722a97ca4064dea3eaf00bb51654 Mon Sep 17 00:00:00 2001 From: dormantman Date: Thu, 5 Dec 2019 18:10:24 +0300 Subject: [PATCH 2/8] Merge branch 'fix/dublicate-products' of /home/dormantman/PycharmProjects/gm-backend with conflicts. --- .gitignore | 6 ++---- apps/product/views/common.py | 2 ++ project/settings/local.py | 36 +++++++++++++----------------------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index 90e4f23f..ea6151b0 100644 --- a/.gitignore +++ b/.gitignore @@ -21,10 +21,8 @@ logs/ /geoip_db/ # dev -./docker-compose.override.yml +docker-compose.override.yml + celerybeat-schedule local_files celerybeat.pid -/gm_viktor.dump -/docker-compose.dump.yml -/gm_production_20191029.sql diff --git a/apps/product/views/common.py b/apps/product/views/common.py index f984a87b..764a0c97 100644 --- a/apps/product/views/common.py +++ b/apps/product/views/common.py @@ -26,6 +26,8 @@ class ProductListView(ProductBaseView, generics.ListAPIView): filter_class = filters.ProductFilterSet def get_queryset(self): + print(super().get_queryset()) + qs = super().get_queryset().with_extended_related() \ .by_country_code(self.request.country_code) return qs diff --git a/project/settings/local.py b/project/settings/local.py index c56f9042..fe521d92 100644 --- a/project/settings/local.py +++ b/project/settings/local.py @@ -30,31 +30,18 @@ MEDIA_ROOT = os.path.join(PUBLIC_ROOT, MEDIA_LOCATION) THUMBNAIL_DEBUG = True # ADDED TRANSFER APP -INSTALLED_APPS.append('transfer.apps.TransferConfig') +# INSTALLED_APPS.append('transfer.apps.TransferConfig') # DATABASES -DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': os.environ.get('DB_NAME'), - 'USER': os.environ.get('DB_USERNAME'), - 'PASSWORD': os.environ.get('DB_PASSWORD'), - 'HOST': os.environ.get('DB_HOSTNAME'), - 'PORT': os.environ.get('DB_PORT'), - 'OPTIONS': { - 'options': '-c search_path=gm' - }, - }, - 'legacy': { - 'ENGINE': 'django.db.backends.mysql', - # 'HOST': '172.22.0.1', - 'HOST': 'mysql_db', - 'PORT': 3306, - 'NAME': 'dev', - 'USER': 'dev', - 'PASSWORD': 'octosecret123' - }, -} +# DATABASES.update({ +# 'legacy': { +# 'ENGINE': 'django.db.backends.mysql', +# # 'HOST': '172.22.0.1', +# 'HOST': 'mysql_db', +# 'PORT': 3306, +# 'NAME': 'dev', +# 'USER': 'dev', +# 'PASSWORD': 'octosecret123'}}) # LOGGING @@ -113,3 +100,6 @@ TESTING = sys.argv[1:2] == ['test'] if TESTING: ELASTICSEARCH_INDEX_NAMES = {} ELASTICSEARCH_DSL_AUTOSYNC = False + +# INSTALLED APPS +INSTALLED_APPS.append('transfer.apps.TransferConfig') \ No newline at end of file From 0c5140d35944328b2916b6eabaa04ec8677b23a5 Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 6 Dec 2019 15:03:18 +0300 Subject: [PATCH 3/8] Added current product exclude --- apps/product/filters.py | 6 ++++++ apps/product/models.py | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/apps/product/filters.py b/apps/product/filters.py index c7e87dda..1d226356 100644 --- a/apps/product/filters.py +++ b/apps/product/filters.py @@ -9,6 +9,7 @@ class ProductFilterSet(filters.FilterSet): """Product filter set.""" establishment_id = filters.NumberFilter() + current_product = filters.CharFilter(method='without_current_product') product_type = filters.CharFilter(method='by_product_type') product_subtype = filters.CharFilter(method='by_product_subtype') @@ -21,6 +22,11 @@ class ProductFilterSet(filters.FilterSet): 'product_subtype', ] + def without_current_product(self, queryset, name, value): + if value not in EMPTY_VALUES: + return queryset.without_current_product(value) + return queryset + def by_product_type(self, queryset, name, value): if value not in EMPTY_VALUES: return queryset.by_product_type(value) diff --git a/apps/product/models.py b/apps/product/models.py index a6129c48..6d3e4954 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -102,6 +102,11 @@ class ProductQuerySet(models.QuerySet): def wines(self): return self.filter(type__index_name__icontains=ProductType.WINE) + def without_current_product(self, current_product: str): + """Exclude by current product.""" + kwargs = {'pk': int(current_product)} if current_product.isdigit() else {'slug': current_product} + return self.exclude(**kwargs) + def by_product_type(self, product_type: str): """Filter by type.""" return self.filter(product_type__index_name__icontains=product_type) From 6a9356aaa6b9efc7f5a41ff32a58c2b37196bf76 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 6 Dec 2019 15:10:48 +0300 Subject: [PATCH 4/8] fix merge conflicts --- .gitignore | 6 ++++-- apps/product/views/common.py | 2 -- project/settings/local.py | 36 +++++++++++++++++++++++------------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index ea6151b0..90e4f23f 100644 --- a/.gitignore +++ b/.gitignore @@ -21,8 +21,10 @@ logs/ /geoip_db/ # dev -docker-compose.override.yml - +./docker-compose.override.yml celerybeat-schedule local_files celerybeat.pid +/gm_viktor.dump +/docker-compose.dump.yml +/gm_production_20191029.sql diff --git a/apps/product/views/common.py b/apps/product/views/common.py index 764a0c97..f984a87b 100644 --- a/apps/product/views/common.py +++ b/apps/product/views/common.py @@ -26,8 +26,6 @@ class ProductListView(ProductBaseView, generics.ListAPIView): filter_class = filters.ProductFilterSet def get_queryset(self): - print(super().get_queryset()) - qs = super().get_queryset().with_extended_related() \ .by_country_code(self.request.country_code) return qs diff --git a/project/settings/local.py b/project/settings/local.py index fe521d92..c56f9042 100644 --- a/project/settings/local.py +++ b/project/settings/local.py @@ -30,18 +30,31 @@ MEDIA_ROOT = os.path.join(PUBLIC_ROOT, MEDIA_LOCATION) THUMBNAIL_DEBUG = True # ADDED TRANSFER APP -# INSTALLED_APPS.append('transfer.apps.TransferConfig') +INSTALLED_APPS.append('transfer.apps.TransferConfig') # DATABASES -# DATABASES.update({ -# 'legacy': { -# 'ENGINE': 'django.db.backends.mysql', -# # 'HOST': '172.22.0.1', -# 'HOST': 'mysql_db', -# 'PORT': 3306, -# 'NAME': 'dev', -# 'USER': 'dev', -# 'PASSWORD': 'octosecret123'}}) +DATABASES = { + 'default': { + 'ENGINE': 'django.contrib.gis.db.backends.postgis', + 'NAME': os.environ.get('DB_NAME'), + 'USER': os.environ.get('DB_USERNAME'), + 'PASSWORD': os.environ.get('DB_PASSWORD'), + 'HOST': os.environ.get('DB_HOSTNAME'), + 'PORT': os.environ.get('DB_PORT'), + 'OPTIONS': { + 'options': '-c search_path=gm' + }, + }, + 'legacy': { + 'ENGINE': 'django.db.backends.mysql', + # 'HOST': '172.22.0.1', + 'HOST': 'mysql_db', + 'PORT': 3306, + 'NAME': 'dev', + 'USER': 'dev', + 'PASSWORD': 'octosecret123' + }, +} # LOGGING @@ -100,6 +113,3 @@ TESTING = sys.argv[1:2] == ['test'] if TESTING: ELASTICSEARCH_INDEX_NAMES = {} ELASTICSEARCH_DSL_AUTOSYNC = False - -# INSTALLED APPS -INSTALLED_APPS.append('transfer.apps.TransferConfig') \ No newline at end of file From 351d4920121049e0b00c3563abd6d48091969da0 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 6 Dec 2019 15:45:46 +0300 Subject: [PATCH 5/8] command to remove relative news description images --- .../news/management/commands/rm_empty_images.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 apps/news/management/commands/rm_empty_images.py diff --git a/apps/news/management/commands/rm_empty_images.py b/apps/news/management/commands/rm_empty_images.py new file mode 100644 index 00000000..3a48e2e4 --- /dev/null +++ b/apps/news/management/commands/rm_empty_images.py @@ -0,0 +1,17 @@ +from django.core.management.base import BaseCommand + +from news.models import News +import re + +class Command(BaseCommand): + help = 'Removes empty img html tags from news description' + + relative_img_regex = re.compile(r'\', re.I) + + def handle(self, *args, **kwargs): + for news in News.objects.all(): + if isinstance(news.description, dict): + news.description = {locale: self.relative_img_regex.sub('', rich_text) + for locale, rich_text in news.description.items()} + self.stdout.write(self.style.WARNING(f'Replaced {news} empty img html tags...\n')) + news.save() \ No newline at end of file From bdb82d0fb010632fcfb64b9a056e3e163f4407cc Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 6 Dec 2019 16:40:39 +0300 Subject: [PATCH 6/8] add migration command --- make_data_migration.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/make_data_migration.sh b/make_data_migration.sh index 70e27ccb..e6cec3e1 100755 --- a/make_data_migration.sh +++ b/make_data_migration.sh @@ -12,4 +12,5 @@ ./manage.py transfer --wine_characteristics ./manage.py transfer --inquiries ./manage.py transfer --assemblage -./manage.py transfer --purchased_plaques \ No newline at end of file +./manage.py transfer --purchased_plaques +./manage.py rm_empty_images \ No newline at end of file From 8af8cf92e97d97c52a0617a05cd7c99d6f511996 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Fri, 6 Dec 2019 17:00:54 +0300 Subject: [PATCH 7/8] added objects related statistic in Collection backoffice serializer --- apps/collection/models.py | 36 +++++++++++++++++++++++++++++ apps/collection/serializers/back.py | 4 ++++ 2 files changed, 40 insertions(+) diff --git a/apps/collection/models.py b/apps/collection/models.py index 58ca9f07..7acd9991 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -87,6 +87,42 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, verbose_name = _('collection') verbose_name_plural = _('collections') + @property + def _related_objects(self) -> list: + """Return list of related objects.""" + related_objects = [] + # get related objects + for related_object in self._meta.related_objects: + related_objects.append(related_object) + return related_objects + + @property + def count_related_objects(self) -> int: + """Return count of related objects.""" + counter = 0 + # count of related objects + for related_object in [related_object.name for related_object in self._related_objects]: + counter += getattr(self, f'{related_object}').count() + return counter + + @property + def related_object_names(self) -> list: + """Return related object names.""" + raw_object_names = [] + for related_object in [related_object.name for related_object in self._related_objects]: + instances = getattr(self, f'{related_object}') + if instances.exists(): + for instance in instances.all(): + raw_object_names.append(instance.slug if hasattr(instance, 'slug') else None) + + # parse slugs + object_names = [] + re_pattern = r'[\w]+' + for raw_name in raw_object_names: + result = re.findall(re_pattern, raw_name) + if result: object_names.append(' '.join(result).capitalize()) + return set(object_names) + class GuideTypeQuerySet(models.QuerySet): """QuerySet for model GuideType.""" diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index bb88a778..48c25f6c 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -19,6 +19,8 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): collection_type_display = serializers.CharField( source='get_collection_type_display', read_only=True) country = CountrySimpleSerializer(read_only=True) + count_related_objects = serializers.IntegerField(read_only=True) + related_object_names = serializers.ListField(read_only=True) class Meta: model = models.Collection @@ -36,6 +38,8 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'slug', 'start', 'end', + 'count_related_objects', + 'related_object_names', ] From f1fa8a58de3c3d7a9eb6d90b99b8d57332e3e6f1 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Fri, 6 Dec 2019 17:37:33 +0300 Subject: [PATCH 8/8] small refactoring --- apps/establishment/views/web.py | 5 +---- apps/product/views/common.py | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index 71994522..74c20451 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -114,10 +114,7 @@ class EstablishmentCommentListView(generics.ListAPIView): """Override get_queryset method""" establishment = get_object_or_404(models.Establishment, slug=self.kwargs['slug']) - return comment_models.Comment.objects.by_content_type(app_label='establishment', - model='establishment') \ - .by_object_id(object_id=establishment.pk) \ - .order_by('-created') + return establishment.comments.order_by('-created') class EstablishmentCommentRUDView(generics.RetrieveUpdateDestroyAPIView): diff --git a/apps/product/views/common.py b/apps/product/views/common.py index f984a87b..650c1dfe 100644 --- a/apps/product/views/common.py +++ b/apps/product/views/common.py @@ -60,10 +60,7 @@ class ProductCommentListView(generics.ListAPIView): def get_queryset(self): """Override get_queryset method""" product = get_object_or_404(Product, slug=self.kwargs['slug']) - return Comment.objects.by_content_type(app_label='product', - model='product') \ - .by_object_id(object_id=product.pk) \ - .order_by('-created') + return product.comments.order_by('-created') class ProductCommentRUDView(generics.RetrieveUpdateDestroyAPIView):