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', ] 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/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 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/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) 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): diff --git a/docker-compose.mysql.yml b/docker-compose.mysql.yml index a8900226..008acb0b 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 diff --git a/make_data_migration.sh b/make_data_migration.sh index 13fba591..50be7fc4 100755 --- a/make_data_migration.sh +++ b/make_data_migration.sh @@ -14,4 +14,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