diff --git a/apps/tag/serializers.py b/apps/tag/serializers.py index eb73291f..2fea5ad0 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,72 @@ class TagCategoryBaseSerializer(serializers.ModelSerializer): return TagBaseSerializer(instance=tags, many=True, read_only=True).data +class FiltersTagCategoryBaseSerializer(serializers.ModelSerializer): + """Serializer for model TagCategory.""" + + label_translated = TranslatedField() + filters = SerializerMethodField() + param_name = SerializerMethodField() + type = SerializerMethodField() + + class Meta: + """Meta class.""" + + model = models.TagCategory + fields = ( + 'id', + '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) + + 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..23298d3d 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'filters', views.FiltersTagCategoryViewSet) router.register(r'chosen_tags', views.ChosenTagsView) urlpatterns = [ diff --git a/apps/tag/views.py b/apps/tag/views.py index 4a2f2613..db3970e5 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -1,11 +1,17 @@ """Tag views.""" from django.conf import settings +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 location.models import WineRegion +from tag import filters +from tag import models +from tag import serializers class ChosenTagsView(generics.ListAPIView, viewsets.GenericViewSet): @@ -36,7 +42,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 +60,104 @@ class TagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): serializer_class = serializers.TagCategoryBaseSerializer +# User`s views & viewsets +class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): + """ViewSet for TagCategory model.""" + + filterset_class = filters.TagCategoryFilterSet + pagination_class = None + permission_classes = (permissions.AllowAny,) + queryset = models.TagCategory.objects.with_tags().with_base_related(). \ + distinct() + serializer_class = serializers.FiltersTagCategoryBaseSerializer + + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + serializer = self.get_serializer(queryset, many=True) + + result_list = serializer.data + query_params = request.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", + "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 params_type == 'winery' and '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 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", + "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 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 evening", + "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 params_type in ('restaurant', 'artisan') and '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) + + 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) + + # BackOffice user`s views & viewsets class BindObjectMixin: """Bind object mixin."""