From db5c879459007e8bb2c61bba3d62e50140860e76 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Mon, 23 Dec 2019 17:53:48 +0300 Subject: [PATCH] refactored method to get similar list on entities (see todo: establishment/models.py) --- apps/collection/admin.py | 31 ++++++- apps/collection/models.py | 119 ++++++++++++++++++++++++-- apps/collection/serializers/common.py | 11 +-- apps/collection/tasks.py | 21 +++++ apps/product/admin.py | 2 + 5 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 apps/collection/tasks.py diff --git a/apps/collection/admin.py b/apps/collection/admin.py index 1b876e91..68a6cd6b 100644 --- a/apps/collection/admin.py +++ b/apps/collection/admin.py @@ -1,10 +1,35 @@ from django.contrib.gis import admin -from mptt.admin import DraggableMPTTAdmin, TreeRelatedFieldListFilter +from mptt.admin import DraggableMPTTAdmin from utils.admin import BaseModelAdminMixin from collection import models +class GuideFilterInline(admin.TabularInline): + """Tabular inline for GuideFilter model.""" + extra = 0 + model = models.GuideFilter + + +class GuideElementInline(admin.TabularInline): + """Tabular inline for GuideElement model.""" + extra = 0 + model = models.GuideElement + raw_id_fields = [ + 'guide_element_type', + 'establishment', + 'review', + 'wine_region', + 'product', + 'city', + 'wine_color_section', + 'section', + 'guide', + 'parent', + 'label_photo', + ] + + @admin.register(models.Collection) class CollectionAdmin(admin.ModelAdmin): """Collection admin.""" @@ -13,6 +38,7 @@ class CollectionAdmin(admin.ModelAdmin): @admin.register(models.Guide) class GuideAdmin(admin.ModelAdmin): """Guide admin.""" + inlines = [GuideFilterInline, ] @admin.register(models.GuideElementType) @@ -29,6 +55,3 @@ class GuideElementAdmin(DraggableMPTTAdmin, BaseModelAdminMixin, admin.ModelAdmi 'wine_color_section', 'section', 'guide', 'parent', ] - # list_filter = ( - # ('parent', TreeRelatedFieldListFilter), - # ) diff --git a/apps/collection/models.py b/apps/collection/models.py index 58789dfe..90b36f52 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -6,17 +6,17 @@ from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.utils.translation import gettext_lazy as _ from mptt.models import MPTTModel, TreeForeignKey +from django.conf import settings +from collection import tasks from location.models import Country, Region, WineRegion, WineSubRegion from review.models import Review from translation.models import Language -from utils.models import IntermediateGalleryModelMixin, GalleryModelMixin from utils.models import ( ProjectBaseMixin, TJSONField, TranslatedFieldsMixin, - URLImageMixin, + URLImageMixin, IntermediateGalleryModelMixin ) from utils.querysets import RelatedObjectsCountMixin -from utils.models import IntermediateGalleryModelMixin, GalleryMixin # Mixins @@ -434,6 +434,13 @@ class GuideFilter(ProjectBaseMixin): model=EstablishmentType, lookup_field='index_name') + @property + def establishment_type_ids(self): + from establishment.models import EstablishmentType + return self.get_value_list(json_field=self.establishment_type_json, + model=EstablishmentType, + lookup_field='id') + @property def locales(self): return self.get_value_list(json_field=self.locale_json, @@ -456,6 +463,12 @@ class GuideFilter(ProjectBaseMixin): model=Country, lookup_field='name_translated') + @property + def country_ids(self): + return self.get_value_list(json_field=self.country_json, + model=Country, + lookup_field='id') + @property def region_names(self): return self.get_value_list(json_field=self.region_json, @@ -463,15 +476,96 @@ class GuideFilter(ProjectBaseMixin): lookup_field='name') @property - def sub_region_names(self): + def region_ids(self): return self.get_value_list(json_field=self.region_json, - model=Country, + model=Region, + lookup_field='id') + + @property + def sub_region_names(self): + return self.get_value_list(json_field=self.sub_region_json, + model=Region, lookup_field='name_translated') + @property + def sub_region_ids(self): + return self.get_value_list(json_field=self.sub_region_json, + model=Region, + lookup_field='id') + + @property + def wine_region_ids(self): + return self.get_value_list(json_field=self.wine_region_json, + model=WineRegion, + lookup_field='id') + @property def review_vintages(self): return self.review_vintage_json.get('vintage') + @property + def available_filters(self): + filters = list() + for i in self._meta.fields: + if isinstance(i, JSONField): + has_values = list(getattr(self, f'{i.name}').values())[0] + if has_values: + filters.append(i.name) + return filters + + @property + def establishment_filter_set(self): + filters = { + # establishment.Establishment + 'public_mark__in': [self.min_mark, self.max_mark], + # review.Reviews + 'reviews__vintage__in': self.review_vintages, + } + + if self.establishment_type_ids: + filters.update({ + # establishment.EstablishmentType + 'establishment_type_id__in': self.establishment_type_ids, + }) + + if self.country_ids: + filters.update({ + # location.Country + 'address__city__country_id__in': self.country_ids, + }) + + if self.region_ids: + filters.update({ + # location.Region + 'address__city__region__parent_id__in': self.region_ids, + }) + + if self.sub_region_ids: + filters.update({ + # location.Region + 'address__city__region__parent_id__in': self.region_ids, + 'address__city__region_id__in': self.sub_region_ids, + }) + + if self.wine_region_ids: + filters.update({ + # location.WineRegion + 'wine_region_id__in': self.wine_region_ids, + }) + + if self.with_mark: + filters.update({ + # establishment.Establishment + 'public_mark__isnull': False, + }) + + if self.locale_json: + filters.update({ + 'reviews__text__has_any_keys': self.locales, + }) + + return filters + class GuideElementType(models.Model): """Model for type of guide elements.""" @@ -558,6 +652,21 @@ class GuideElementManager(models.Manager): class GuideElementQuerySet(models.QuerySet): """QuerySet for model Guide elements.""" + def base_related(self): + """Return QuerySet with base related.""" + return self.select_related( + 'guide_element_type', + 'establishment', + 'review', + 'wine_region', + 'product', + 'city', + 'wine_color_section', + 'section', + 'guide', + 'label_photo', + ) + def restaurant_nodes(self): """Return GuideElement with type RestaurantSectionNode.""" return self.filter(guide_element_type__name='RestaurantSectionNode') diff --git a/apps/collection/serializers/common.py b/apps/collection/serializers/common.py index f13cbdfb..9d3e81e9 100644 --- a/apps/collection/serializers/common.py +++ b/apps/collection/serializers/common.py @@ -7,6 +7,7 @@ from utils.serializers import TranslatedField from rest_framework_recursive.fields import RecursiveField from establishment.serializers import EstablishmentGuideElementSerializer from product.serializers import ProductGuideElementSerializer +from django.shortcuts import get_object_or_404 class CollectionBaseSerializer(serializers.ModelSerializer): @@ -161,13 +162,12 @@ class GuideFilterBaseSerializer(serializers.ModelSerializer): """Get url kwargs from request.""" return self.context.get('request').parser_context.get('kwargs') - def get_guide(self): - """Get guide instance from kwargs.""" - return self.request_kwargs.get() - def create(self, validated_data): """Overridden create method.""" - validated_data['guide'] = self.get_guide(validated_data.pop('guide', None)) + guide = get_object_or_404(models.Guide.objects.all(), + pk=self.request_kwargs.get('pk')) + validated_data['guide'] = guide + return super().create(validated_data) @@ -190,6 +190,7 @@ class GuideElementBaseSerializer(serializers.ModelSerializer): """Meta class.""" model = models.GuideElement fields = [ + 'id', 'node_name', 'establishment_detail', 'review', diff --git a/apps/collection/tasks.py b/apps/collection/tasks.py new file mode 100644 index 00000000..b9758271 --- /dev/null +++ b/apps/collection/tasks.py @@ -0,0 +1,21 @@ +"""Collectoin app celery tasks.""" +import logging + +from celery import shared_task +from django.utils.translation import gettext_lazy as _ + +from collection import models as collection_models + +logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO) +logger = logging.getLogger(__name__) + + +# todo: finish this +@shared_task +def generate_guide_elements(guide_id: int): + """Send verification email to user.""" + try: + obj = collection_models.Guide.objects.get(id=guide_id) + except Exception as e: + logger.error(f'METHOD_NAME: {generate_guide_elements.__name__}\n' + f'DETAIL: guide {guide_id}, - {e}') diff --git a/apps/product/admin.py b/apps/product/admin.py index 182be5c3..af6d7cb9 100644 --- a/apps/product/admin.py +++ b/apps/product/admin.py @@ -25,11 +25,13 @@ class ProductAdmin(BaseModelAdminMixin, admin.ModelAdmin): @admin.register(ProductType) class ProductTypeAdmin(admin.ModelAdmin): """Admin page for model ProductType.""" + raw_id_fields = ['tag_categories', 'default_image'] @admin.register(ProductSubType) class ProductSubTypeAdmin(admin.ModelAdmin): """Admin page for model ProductSubType.""" + raw_id_fields = ['product_type', 'default_image'] @admin.register(Unit)