From 4ec812d617e9d2aa5c27feb5632f47e5360c61a9 Mon Sep 17 00:00:00 2001 From: dormantman Date: Tue, 10 Dec 2019 14:27:16 +0300 Subject: [PATCH 1/3] Created new category_test url --- apps/tag/serializers.py | 48 ++++++++++++-- apps/tag/urls/web.py | 1 + apps/tag/views.py | 134 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 176 insertions(+), 7 deletions(-) diff --git a/apps/tag/serializers.py b/apps/tag/serializers.py index eb73291f..2da41d5c 100644 --- a/apps/tag/serializers.py +++ b/apps/tag/serializers.py @@ -2,11 +2,14 @@ from rest_framework import serializers from rest_framework.fields import SerializerMethodField -from establishment.models import (Establishment, EstablishmentType) -from news.models import News, NewsType +from establishment.models import Establishment +from establishment.models import EstablishmentType +from news.models import News +from news.models import NewsType from tag import models -from utils.exceptions import (ObjectAlreadyAdded, BindingObjectNotFound, - RemovedBindingObjectNotFound) +from utils.exceptions import BindingObjectNotFound +from utils.exceptions import ObjectAlreadyAdded +from utils.exceptions import RemovedBindingObjectNotFound from utils.serializers import TranslatedField @@ -95,6 +98,43 @@ class TagCategoryBaseSerializer(serializers.ModelSerializer): return TagBaseSerializer(instance=tags, many=True, read_only=True).data +class TestBaseSerializer(serializers.ModelSerializer): + """Serializer for model TagCategory.""" + + label_translated = TranslatedField() + tags = SerializerMethodField() + + class Meta: + """Meta class.""" + + model = models.TagCategory + fields = ( + 'id', + 'transliterated_name', + 'name', + 'tags', + ) + + def get_filters(self, obj): + query_params = dict(self.context['request'].query_params) + + if len(query_params) > 1: + return [] + + params = {} + if 'establishment_type' in query_params: + params = { + 'establishments__isnull': False, + } + elif 'product_type' in query_params: + params = { + 'products__isnull': False, + } + + tags = obj.tags.filter(**params).distinct() + return TagBaseSerializer(instance=tags, many=True, read_only=True).data + + class TagCategoryShortSerializer(serializers.ModelSerializer): """Serializer for model TagCategory.""" diff --git a/apps/tag/urls/web.py b/apps/tag/urls/web.py index f83c593a..7ea45b17 100644 --- a/apps/tag/urls/web.py +++ b/apps/tag/urls/web.py @@ -7,6 +7,7 @@ app_name = 'tag' router = SimpleRouter() router.register(r'categories', views.TagCategoryViewSet) +router.register(r'categories_test', views.TestTagCategoryViewSet) router.register(r'chosen_tags', views.ChosenTagsView) urlpatterns = [ diff --git a/apps/tag/views.py b/apps/tag/views.py index 4a2f2613..886d4f9f 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -1,11 +1,25 @@ """Tag views.""" from django.conf import settings +from django_elasticsearch_dsl_drf import constants +from django_elasticsearch_dsl_drf.filter_backends import FilteringFilterBackend +from elasticsearch_dsl import TermsFacet +from rest_framework import generics +from rest_framework import mixins from rest_framework import permissions -from rest_framework import viewsets, mixins, status, generics +from rest_framework import status +from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.response import Response -from tag import filters, models, serializers +from search_indexes import utils +from search_indexes.documents import EstablishmentDocument +from search_indexes.filters import CustomFacetedSearchFilterBackend +from search_indexes.filters import CustomSearchFilterBackend +from search_indexes.serializers import EstablishmentDocumentSerializer +from tag import filters +from tag import models +from tag import serializers +from utils.pagination import ESDocumentPagination class ChosenTagsView(generics.ListAPIView, viewsets.GenericViewSet): @@ -36,7 +50,8 @@ class ChosenTagsView(generics.ListAPIView, viewsets.GenericViewSet): serializer = self.get_serializer(queryset, many=True) result_list = serializer.data if request.query_params.get('type') and (settings.ESTABLISHMENT_CHOSEN_TAGS or settings.NEWS_CHOSEN_TAGS): - ordered_list = settings.ESTABLISHMENT_CHOSEN_TAGS if request.query_params.get('type') == 'establishment' else settings.NEWS_CHOSEN_TAGS + ordered_list = settings.ESTABLISHMENT_CHOSEN_TAGS if request.query_params.get( + 'type') == 'establishment' else settings.NEWS_CHOSEN_TAGS result_list = sorted(result_list, key=lambda x: ordered_list.index(x['index_name'])) return Response(result_list) @@ -53,6 +68,119 @@ class TagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = serializers.TagCategoryBaseSerializer +# User`s views & viewsets +class TestTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): + """ViewSet for TagCategory model.""" + + filterset_classes = [ + filters.TagCategoryFilterSet, + FilteringFilterBackend, + CustomSearchFilterBackend, + CustomFacetedSearchFilterBackend, + ] + + document = EstablishmentDocument + pagination_class = ESDocumentPagination + permission_classes = (permissions.AllowAny,) + queryset = models.TagCategory.objects.with_tags().with_base_related(). \ + distinct() + serializer_class = serializers.TestBaseSerializer + + faceted_search_fields = { + 'works_at_weekday': { + 'field': 'works_at_weekday', + 'facet': TermsFacet, + 'enabled': True, + }, + 'toque_number': { + 'field': 'toque_number', + 'enabled': True, + 'facet': TermsFacet, + }, + 'works_noon': { + 'field': 'works_noon', + 'facet': TermsFacet, + 'enabled': True, + }, + 'works_evening': { + 'field': 'works_evening', + 'facet': TermsFacet, + 'enabled': True, + }, + 'works_now': { + 'field': 'works_now', + 'facet': TermsFacet, + 'enabled': True, + }, + 'tag': { + 'field': 'tags.id', + 'facet': TermsFacet, + 'enabled': True, + 'options': { + 'size': utils.FACET_MAX_RESPONSE, + }, + } + } + + search_fields = { + 'name': { + 'fuzziness': 'auto:2,5', + 'boost': 4 + }, + 'transliterated_name': { + 'fuzziness': 'auto:2,5', + 'boost': 3 + }, + 'description': {'fuzziness': 'auto:2,5'}, + } + translated_search_fields = ( + 'description', + ) + filter_fields = { + 'slug': 'slug', + 'tag': { + 'field': 'tags.id', + 'lookups': [constants.LOOKUP_QUERY_IN] + }, + 'toque_number': { + 'field': 'toque_number', + 'lookups': [ + constants.LOOKUP_FILTER_RANGE, + constants.LOOKUP_QUERY_GT, + constants.LOOKUP_QUERY_GTE, + constants.LOOKUP_QUERY_LT, + constants.LOOKUP_QUERY_LTE, + constants.LOOKUP_QUERY_IN, + ] + }, + + 'works_noon': { + 'field': 'works_noon', + 'lookups': [ + constants.LOOKUP_QUERY_IN, + ], + }, + 'works_at_weekday': { + 'field': 'works_at_weekday', + 'lookups': [ + constants.LOOKUP_QUERY_IN, + ], + }, + 'works_evening': { + 'field': 'works_evening', + 'lookups': [ + constants.LOOKUP_QUERY_IN, + ], + }, + 'works_now': { + 'field': 'works_now', + 'lookups': [ + constants.LOOKUP_FILTER_TERM, + ] + }, + } + + # BackOffice user`s views & viewsets class BindObjectMixin: """Bind object mixin.""" From 096d5dab1829d6f4f1b0f3d34c17355fca9ee32a Mon Sep 17 00:00:00 2001 From: dormantman Date: Tue, 10 Dec 2019 19:24:56 +0300 Subject: [PATCH 2/3] Added tags/filters method --- apps/tag/serializers.py | 45 ++++++++-- apps/tag/urls/web.py | 2 +- apps/tag/views.py | 191 +++++++++++++++++----------------------- 3 files changed, 120 insertions(+), 118 deletions(-) diff --git a/apps/tag/serializers.py b/apps/tag/serializers.py index 2da41d5c..2fea5ad0 100644 --- a/apps/tag/serializers.py +++ b/apps/tag/serializers.py @@ -98,11 +98,13 @@ class TagCategoryBaseSerializer(serializers.ModelSerializer): return TagBaseSerializer(instance=tags, many=True, read_only=True).data -class TestBaseSerializer(serializers.ModelSerializer): +class FiltersTagCategoryBaseSerializer(serializers.ModelSerializer): """Serializer for model TagCategory.""" label_translated = TranslatedField() - tags = SerializerMethodField() + filters = SerializerMethodField() + param_name = SerializerMethodField() + type = SerializerMethodField() class Meta: """Meta class.""" @@ -110,17 +112,44 @@ class TestBaseSerializer(serializers.ModelSerializer): model = models.TagCategory fields = ( 'id', - 'transliterated_name', - 'name', - 'tags', + 'label_translated', + 'index_name', + 'param_name', + 'type', + 'filters', ) + def get_type(self, obj): + return obj in ['open_now', ] + + def get_param_name(self, obj): + if obj == 'service': + return 'tags_id__in' + + elif obj == 'pop': + return 'tags_id__in' + + elif obj == 'open_now': + return 'open_now' + + elif obj == 'wine_region': + return 'wine_region_id__in' + + return '%s__in' % obj.index_name + + def get_fields(self, *args, **kwargs): + fields = super(FiltersTagCategoryBaseSerializer, self).get_fields() + + if self.get_type(self): + fields.pop('filters', None) + else: + fields.pop('type', None) + + return fields + def get_filters(self, obj): query_params = dict(self.context['request'].query_params) - if len(query_params) > 1: - return [] - params = {} if 'establishment_type' in query_params: params = { diff --git a/apps/tag/urls/web.py b/apps/tag/urls/web.py index 7ea45b17..23298d3d 100644 --- a/apps/tag/urls/web.py +++ b/apps/tag/urls/web.py @@ -7,7 +7,7 @@ app_name = 'tag' router = SimpleRouter() router.register(r'categories', views.TagCategoryViewSet) -router.register(r'categories_test', views.TestTagCategoryViewSet) +router.register(r'filters', views.FiltersTagCategoryViewSet) router.register(r'chosen_tags', views.ChosenTagsView) urlpatterns = [ diff --git a/apps/tag/views.py b/apps/tag/views.py index 886d4f9f..fc870fe9 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -11,15 +11,10 @@ from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.response import Response -from search_indexes import utils -from search_indexes.documents import EstablishmentDocument -from search_indexes.filters import CustomFacetedSearchFilterBackend -from search_indexes.filters import CustomSearchFilterBackend -from search_indexes.serializers import EstablishmentDocumentSerializer +from location.models import WineRegion from tag import filters from tag import models from tag import serializers -from utils.pagination import ESDocumentPagination class ChosenTagsView(generics.ListAPIView, viewsets.GenericViewSet): @@ -69,116 +64,94 @@ class TagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): # User`s views & viewsets -class TestTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): +class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ViewSet for TagCategory model.""" - filterset_classes = [ - filters.TagCategoryFilterSet, - FilteringFilterBackend, - CustomSearchFilterBackend, - CustomFacetedSearchFilterBackend, - ] - - document = EstablishmentDocument - pagination_class = ESDocumentPagination + filterset_class = filters.TagCategoryFilterSet + pagination_class = None permission_classes = (permissions.AllowAny,) queryset = models.TagCategory.objects.with_tags().with_base_related(). \ distinct() - serializer_class = serializers.TestBaseSerializer + serializer_class = serializers.FiltersTagCategoryBaseSerializer - faceted_search_fields = { - 'works_at_weekday': { - 'field': 'works_at_weekday', - 'facet': TermsFacet, - 'enabled': True, - }, - 'toque_number': { - 'field': 'toque_number', - 'enabled': True, - 'facet': TermsFacet, - }, - 'works_noon': { - 'field': 'works_noon', - 'facet': TermsFacet, - 'enabled': True, - }, - 'works_evening': { - 'field': 'works_evening', - 'facet': TermsFacet, - 'enabled': True, - }, - 'works_now': { - 'field': 'works_now', - 'facet': TermsFacet, - 'enabled': True, - }, - 'tag': { - 'field': 'tags.id', - 'facet': TermsFacet, - 'enabled': True, - 'options': { - 'size': utils.FACET_MAX_RESPONSE, - }, - } - } + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + serializer = self.get_serializer(queryset, many=True) - search_fields = { - 'name': { - 'fuzziness': 'auto:2,5', - 'boost': 4 - }, - 'transliterated_name': { - 'fuzziness': 'auto:2,5', - 'boost': 3 - }, - 'description': {'fuzziness': 'auto:2,5'}, - } - translated_search_fields = ( - 'description', - ) - filter_fields = { - 'slug': 'slug', - 'tag': { - 'field': 'tags.id', - 'lookups': [constants.LOOKUP_QUERY_IN] - }, - 'toque_number': { - 'field': 'toque_number', - 'lookups': [ - constants.LOOKUP_FILTER_RANGE, - constants.LOOKUP_QUERY_GT, - constants.LOOKUP_QUERY_GTE, - constants.LOOKUP_QUERY_LT, - constants.LOOKUP_QUERY_LTE, - constants.LOOKUP_QUERY_IN, - ] - }, + result_list = serializer.data + query_params = request.query_params - 'works_noon': { - 'field': 'works_noon', - 'lookups': [ - constants.LOOKUP_QUERY_IN, - ], - }, - 'works_at_weekday': { - 'field': 'works_at_weekday', - 'lookups': [ - constants.LOOKUP_QUERY_IN, - ], - }, - 'works_evening': { - 'field': 'works_evening', - 'lookups': [ - constants.LOOKUP_QUERY_IN, - ], - }, - 'works_now': { - 'field': 'works_now', - 'lookups': [ - constants.LOOKUP_FILTER_TERM, - ] - }, - } + if 'toque_number__in' in query_params: + toques = { + "index_name": "toque_number", + "label_translated": "Toques", + "param_name": "toque_number__in", + "filters": [{ + "id": toque_id, + "index_name": "toque_%d" % toque_id, + "label_translated": "Toque %d" % toque_id + } for toque_id in range(6)] + } + result_list.append(toques) + + if 'wine_region_id__in' in query_params: + try: + wine_region_id = int(query_params['wine_region_id__in']) + + wine_regions = { + "index_name": "wine_region", + "label_translated": "Wine region", + "param_name": "wine_region_id__in", + "filters": [{ + "id": obj.id, + "index_name": obj.name.lower().replace(' ', '_'), + "label_translated": obj.name + } for obj in WineRegion.objects.filter(id=wine_region_id)] + } + + result_list.append(wine_regions) + + except ValueError: + pass + + if 'works_noon__in' in query_params: + week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") + works_noon = { + "index_name": "works_noon", + "label_translated": "Open noon", + "param_name": "works_noon__in", + "filters": [{ + "id": weekday, + "index_name": week_days[weekday].lower(), + "label_translated": week_days[weekday] + } for weekday in range(7)] + } + result_list.append(works_noon) + + if 'works_evening__in' in query_params: + week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") + works_evening = { + "index_name": "works_evening", + "label_translated": "Open noon", + "param_name": "works_evening__in", + "filters": [{ + "id": weekday, + "index_name": week_days[weekday].lower(), + "label_translated": week_days[weekday] + } for weekday in range(7)] + } + result_list.append(works_evening) + + if 'works_now' in query_params: + works_now = { + "index_name": "open_now", + "label_translated": "Open now", + "param_name": "open_now", + "type": True + } + result_list.append(works_now) + + return Response(result_list) # BackOffice user`s views & viewsets @@ -271,4 +244,4 @@ class TagCategoryBackOfficeViewSet(mixins.CreateModelMixin, if obj_type == self.bind_object_serializer_class.ESTABLISHMENT_TYPE: tag_category.establishment_types.remove(related_object) elif obj_type == self.bind_object_serializer_class.NEWS_TYPE: - tag_category.news_types.remove(related_object) + tag_category.news_types.remove(related_object) \ No newline at end of file From 19c42ab1d7f39c87ea37e1ade639b4d9c567197c Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 13:03:31 +0300 Subject: [PATCH 3/3] Added page types --- apps/tag/views.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/apps/tag/views.py b/apps/tag/views.py index fc870fe9..db3970e5 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -1,8 +1,5 @@ """Tag views.""" from django.conf import settings -from django_elasticsearch_dsl_drf import constants -from django_elasticsearch_dsl_drf.filter_backends import FilteringFilterBackend -from elasticsearch_dsl import TermsFacet from rest_framework import generics from rest_framework import mixins from rest_framework import permissions @@ -81,7 +78,9 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): result_list = serializer.data query_params = request.query_params - if 'toque_number__in' in query_params: + params_type = query_params['type'] + + if params_type == 'restaurant' and 'toque_number__in' in query_params: toques = { "index_name": "toque_number", "label_translated": "Toques", @@ -94,7 +93,7 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } result_list.append(toques) - if 'wine_region_id__in' in query_params: + if params_type == 'winery' and 'wine_region_id__in' in query_params: try: wine_region_id = int(query_params['wine_region_id__in']) @@ -114,7 +113,7 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): except ValueError: pass - if 'works_noon__in' in query_params: + if params_type == 'restaurant' and 'works_noon__in' in query_params: week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") works_noon = { "index_name": "works_noon", @@ -128,11 +127,11 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } result_list.append(works_noon) - if 'works_evening__in' in query_params: + if params_type == 'restaurant' and 'works_evening__in' in query_params: week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") works_evening = { "index_name": "works_evening", - "label_translated": "Open noon", + "label_translated": "Open evening", "param_name": "works_evening__in", "filters": [{ "id": weekday, @@ -142,7 +141,7 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } result_list.append(works_evening) - if 'works_now' in query_params: + if params_type in ('restaurant', 'artisan') and 'works_now' in query_params: works_now = { "index_name": "open_now", "label_translated": "Open now", @@ -151,6 +150,11 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } result_list.append(works_now) + if 'tags_id__in' in query_params: + # filtering by params_type and tags id + # todo: result_list.append( filtering_data ) + pass + return Response(result_list) @@ -244,4 +248,4 @@ class TagCategoryBackOfficeViewSet(mixins.CreateModelMixin, if obj_type == self.bind_object_serializer_class.ESTABLISHMENT_TYPE: tag_category.establishment_types.remove(related_object) elif obj_type == self.bind_object_serializer_class.NEWS_TYPE: - tag_category.news_types.remove(related_object) \ No newline at end of file + tag_category.news_types.remove(related_object)