From 323c2628e02692033bbcc46aa81e54200d4ed601 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Tue, 10 Dec 2019 10:17:58 +0300 Subject: [PATCH 01/15] Add endpoint to get all cities with search string --- apps/location/urls/back.py | 1 + apps/location/views/back.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/apps/location/urls/back.py b/apps/location/urls/back.py index c5ef027b..2434dd26 100644 --- a/apps/location/urls/back.py +++ b/apps/location/urls/back.py @@ -10,6 +10,7 @@ urlpatterns = [ path('addresses//', views.AddressRUDView.as_view(), name='address-RUD'), path('cities/', views.CityListCreateView.as_view(), name='city-list-create'), + path('cities/all/', views.CityListSearchView.as_view(), name='city-list-create'), path('cities//', views.CityRUDView.as_view(), name='city-retrieve'), path('cities//gallery/', views.CityGalleryListView.as_view(), name='gallery-list'), diff --git a/apps/location/views/back.py b/apps/location/views/back.py index 8406dee3..fc4499ae 100644 --- a/apps/location/views/back.py +++ b/apps/location/views/back.py @@ -37,6 +37,15 @@ class CityListCreateView(common.CityViewMixin, generics.ListCreateAPIView): filter_class = filters.CityBackFilter +class CityListSearchView(common.CityViewMixin, generics.ListCreateAPIView): + """Create view for model City.""" + serializer_class = serializers.CitySerializer + permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin] + queryset = models.City.objects.all() + filter_class = filters.CityBackFilter + pagination_class = None + + class CityRUDView(common.CityViewMixin, generics.RetrieveUpdateDestroyAPIView): """RUD view for model City.""" serializer_class = serializers.CitySerializer From 4ec812d617e9d2aa5c27feb5632f47e5360c61a9 Mon Sep 17 00:00:00 2001 From: dormantman Date: Tue, 10 Dec 2019 14:27:16 +0300 Subject: [PATCH 02/15] 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 47cb7f8e63f235f352a8a737188d98f2988c9783 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Tue, 10 Dec 2019 17:09:43 +0300 Subject: [PATCH 03/15] Tmp commit --- apps/account/urls/back.py | 1 + apps/account/views/back.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/apps/account/urls/back.py b/apps/account/urls/back.py index 30f21573..cf1d114e 100644 --- a/apps/account/urls/back.py +++ b/apps/account/urls/back.py @@ -10,4 +10,5 @@ urlpatterns = [ path('user-role/', views.UserRoleLstView.as_view(), name='user-role-list-create'), path('user/', views.UserLstView.as_view(), name='user-create-list'), path('user//', views.UserRUDView.as_view(), name='user-rud'), + path('user//csv', views.get_user_csv, name='user-csv'), ] diff --git a/apps/account/views/back.py b/apps/account/views/back.py index fbbc986e..c1eb32b5 100644 --- a/apps/account/views/back.py +++ b/apps/account/views/back.py @@ -1,6 +1,8 @@ from django_filters.rest_framework import DjangoFilterBackend from rest_framework import generics, permissions from rest_framework.filters import OrderingFilter +import csv +from django.http import HttpResponse, HttpResponseNotFound from account import models from account.models import User @@ -46,3 +48,22 @@ class UserRUDView(generics.RetrieveUpdateDestroyAPIView): serializer_class = serializers.BackDetailUserSerializer permission_classes = (permissions.IsAdminUser,) lookup_field = 'id' + + +def get_user_csv(request, user_id): + try: + user = User.objects.get(id=user_id).values_list() + except User.DoesNotExist: + return HttpResponseNotFound("User not found") + + # + # + # response = HttpResponse(content_type='text/csv') + # response['Content-Disposition'] = f'attachment; filename="{user}.csv"' + # + # writer = csv.writer(response) + # writer.writerow(['First row', 'Foo', 'Bar', 'Baz']) + # writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"]) + # + # return response + return HttpResponseNotFound(user) \ No newline at end of file From 096d5dab1829d6f4f1b0f3d34c17355fca9ee32a Mon Sep 17 00:00:00 2001 From: dormantman Date: Tue, 10 Dec 2019 19:24:56 +0300 Subject: [PATCH 04/15] 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 a254160f439c67481815676e37be6eed5c218ed7 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Wed, 11 Dec 2019 12:10:26 +0300 Subject: [PATCH 05/15] Add account csv endpoint --- apps/account/views/back.py | 74 +++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 13 deletions(-) diff --git a/apps/account/views/back.py b/apps/account/views/back.py index c1eb32b5..92dca84d 100644 --- a/apps/account/views/back.py +++ b/apps/account/views/back.py @@ -3,6 +3,7 @@ from rest_framework import generics, permissions from rest_framework.filters import OrderingFilter import csv from django.http import HttpResponse, HttpResponseNotFound +from rest_framework.authtoken.models import Token from account import models from account.models import User @@ -50,20 +51,67 @@ class UserRUDView(generics.RetrieveUpdateDestroyAPIView): lookup_field = 'id' -def get_user_csv(request, user_id): +def get_user_csv(request, id): + # fields = ["id", "uuid", "nickname", "locale", "country_code", "city", "role", "consent_purpose", "consent_at", + # "last_seen_at", "created_at", "updated_at", "email", "is_admin", "ezuser_id", "ez_user_id", + # "encrypted_password", "reset_password_token", "reset_password_sent_at", "remember_created_at", + # "sign_in_count", "current_sign_in_at", "last_sign_in_at", "current_sign_in_ip", "last_sign_in_ip", + # "confirmation_token", "confirmed_at", "confirmation_sent_at", "unconfirmed_email", "webpush_subscription"] + + # uuid == id + # + # Не найдены: + # consent_purpose + # consent_at + # ezuser_id + # ez_user_id + # remember_created_at + # sign_in_count + # current_sign_in_at + # current_sign_in_ip + # last_sign_in_ip + # confirmed_at + # confirmation_sent_at + # webpush_subscription + # + # country_code не получить - клиент не привязан к стране + try: - user = User.objects.get(id=user_id).values_list() + user = User.objects.get(id=id) except User.DoesNotExist: return HttpResponseNotFound("User not found") - # - # - # response = HttpResponse(content_type='text/csv') - # response['Content-Disposition'] = f'attachment; filename="{user}.csv"' - # - # writer = csv.writer(response) - # writer.writerow(['First row', 'Foo', 'Bar', 'Baz']) - # writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"]) - # - # return response - return HttpResponseNotFound(user) \ No newline at end of file + try: + roles = " ".join([role for role in user.roles]) + except: + roles = "" + + token, _ = Token.objects.get_or_create(user=user) + + fields = { + "id": user.id, + "uuid": user.id, + "username": getattr(user, "username", ""), + "locale": getattr(user, "locale", ""), + "city": getattr(user, "city", ""), + "role": roles, + "created_at": getattr(user, "date_joined", ""), + "updated_at": user.last_login, + "email": user.email, + "is_admin": user.is_superuser, + "encrypted_password": user.password, + "reset_password_token": token.key, + "reset_password_sent_at": token.created, # TODO: не уверен в назначении поля, лучше проверить + "last_sign_in_at": user.last_login, # Повтор? + "confirmation_token": user.confirm_email_token, + "unconfirmed_email": 1 if user.unconfirmed_email else 0 + } + + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = f'attachment; filename="{user.email}.csv"' + + writer = csv.writer(response) + writer.writerow(fields.keys()) + writer.writerow(fields.values()) + + return response From 907a9365e1b73abaa0f55f1cf14ec6fcd0ef22d3 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 11 Dec 2019 12:14:23 +0300 Subject: [PATCH 06/15] fix multislug news update --- apps/news/serializers.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/news/serializers.py b/apps/news/serializers.py index 846bc31a..f22c7129 100644 --- a/apps/news/serializers.py +++ b/apps/news/serializers.py @@ -177,13 +177,23 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer): 'backoffice_title': {'allow_null': False}, } - def validate(self, attrs): - slugs = attrs.get('slugs', {}) - if models.News.objects.filter( - slugs__values__contains=list(slugs.values()) - ).exclude(id=attrs.get('id', 0)).exists(): - raise serializers.ValidationError({'slugs': _('News with this slug already exists.')}) - return attrs + def create(self, validated_data): + slugs = validated_data.get('slugs') + if slugs: + if models.News.objects.filter( + slugs__values__contains=list(slugs.values()) + ).exists(): + raise serializers.ValidationError({'slugs': _('News with this slug already exists.')}) + return super().create(validated_data) + + def update(self, instance, validated_data): + slugs = validated_data.get('slugs') + if slugs: + if models.News.objects.filter( + slugs__values__contains=list(slugs.values()) + ).exclude(pk=instance.pk).exists(): + raise serializers.ValidationError({'slugs': _('News with this slug already exists.')}) + return super().update(instance, validated_data) class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer, From fb5a9d4302581a356258626a0be12a3eefb88ca0 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Wed, 11 Dec 2019 12:26:22 +0300 Subject: [PATCH 07/15] refactored ads --- apps/advertisement/admin.py | 5 +++ apps/advertisement/models.py | 8 ++--- apps/advertisement/serializers/back.py | 30 +++++----------- apps/advertisement/serializers/common.py | 25 ++++++------- apps/advertisement/serializers/mobile.py | 12 +++---- apps/advertisement/serializers/web.py | 12 +++---- apps/advertisement/urls/back.py | 8 ++--- apps/advertisement/views/back.py | 35 +++++++++++-------- apps/advertisement/views/common.py | 6 ++-- apps/main/admin.py | 3 ++ .../migrations/0041_auto_20191211_0631.py | 18 ++++++++++ apps/main/models.py | 3 +- apps/main/serializers.py | 20 +++++++++-- apps/main/urls/back.py | 2 ++ apps/main/views/back.py | 10 +++++- 15 files changed, 121 insertions(+), 76 deletions(-) create mode 100644 apps/main/migrations/0041_auto_20191211_0631.py diff --git a/apps/advertisement/admin.py b/apps/advertisement/admin.py index 3754dca9..2728f4f9 100644 --- a/apps/advertisement/admin.py +++ b/apps/advertisement/admin.py @@ -14,3 +14,8 @@ class PageInline(admin.TabularInline): class AdvertisementModelAdmin(admin.ModelAdmin): """Admin model for model Advertisement""" inlines = (PageInline, ) + list_display = ('id', '__str__', 'block_level', + 'start', 'end', 'page_type') + list_filter = ('url', 'block_level', 'start', 'end', 'page_type', + 'pages__source') + date_hierarchy = 'created' diff --git a/apps/advertisement/models.py b/apps/advertisement/models.py index 66cd0024..b86a6168 100644 --- a/apps/advertisement/models.py +++ b/apps/advertisement/models.py @@ -71,11 +71,11 @@ class Advertisement(ProjectBaseMixin): return super().delete(using, keep_parents) @property - def mobile_page(self): + def mobile_pages(self): """Return mobile page""" - return self.pages.by_platform(Page.MOBILE).first() + return self.pages.by_platform(Page.MOBILE) @property - def web_page(self): + def web_pages(self): """Return web page""" - return self.pages.by_platform(Page.WEB).first() + return self.pages.by_platform(Page.WEB) diff --git a/apps/advertisement/serializers/back.py b/apps/advertisement/serializers/back.py index 9dc8b029..2ca5a18f 100644 --- a/apps/advertisement/serializers/back.py +++ b/apps/advertisement/serializers/back.py @@ -1,26 +1,14 @@ """Serializers for back office app advertisements""" -from main.serializers import PageBaseSerializer +from advertisement.serializers import AdvertisementBaseSerializer +from main.serializers import PageExtendedSerializer -class AdvertisementPageBaseSerializer(PageBaseSerializer): - """Base serializer for linking page w/ advertisement.""" +class AdvertisementDetailSerializer(AdvertisementBaseSerializer): + """Advertisement serializer for back office.""" + pages = PageExtendedSerializer(many=True, read_only=True) - class Meta(PageBaseSerializer.Meta): + class Meta(AdvertisementBaseSerializer.Meta): """Meta class.""" - - PageBaseSerializer.Meta.extra_kwargs.update({ - 'advertisement': {'write_only': True}, - 'image_url': {'required': True}, - 'width': {'required': True}, - 'height': {'required': True}, - }) - - -class AdvertisementPageListCreateSerializer(AdvertisementPageBaseSerializer): - """Serializer for linking page w/ advertisement.""" - - def create(self, validated_data): - """Overridden create method.""" - - validated_data['advertisement'] = self.context.get('view').get_object() - return super().create(validated_data) + fields = AdvertisementBaseSerializer.Meta.fields + [ + 'pages', + ] diff --git a/apps/advertisement/serializers/common.py b/apps/advertisement/serializers/common.py index 9caee0c2..b673475e 100644 --- a/apps/advertisement/serializers/common.py +++ b/apps/advertisement/serializers/common.py @@ -2,15 +2,15 @@ from rest_framework import serializers from advertisement import models -from translation.serializers import LanguageSerializer -from main.serializers import SiteShortSerializer, PageBaseSerializer -from translation.models import Language from main.models import SiteSettings +from main.serializers import PageTypeBaseSerializer +from translation.models import Language class AdvertisementBaseSerializer(serializers.ModelSerializer): """Base serializer for model Advertisement.""" - + page_type_detail = PageTypeBaseSerializer(read_only=True, + source='page_type') target_languages = serializers.PrimaryKeyRelatedField( queryset=Language.objects.all(), many=True, @@ -34,16 +34,17 @@ class AdvertisementBaseSerializer(serializers.ModelSerializer): 'target_sites', 'start', 'end', + 'page_type', + 'page_type_detail', ] + extra_kwargs = { + 'page_type': {'required': True, 'write_only': True} + } -class AdvertisementPageTypeCommonListSerializer(AdvertisementBaseSerializer): - """Serializer for AdvertisementPageTypeCommonView.""" - - page = PageBaseSerializer(source='common_page', read_only=True) - +class AdvertisementSerializer(AdvertisementBaseSerializer): + """Serializer for model Advertisement.""" class Meta(AdvertisementBaseSerializer.Meta): """Meta class.""" - fields = AdvertisementBaseSerializer.Meta.fields + [ - 'page', - ] + fields = AdvertisementBaseSerializer.Meta.fields.copy() + fields.pop(fields.index('page_type_detail')) diff --git a/apps/advertisement/serializers/mobile.py b/apps/advertisement/serializers/mobile.py index 80a19b82..37d810b4 100644 --- a/apps/advertisement/serializers/mobile.py +++ b/apps/advertisement/serializers/mobile.py @@ -1,15 +1,15 @@ """Serializers for mobile app advertisements""" -from advertisement.serializers import AdvertisementBaseSerializer +from advertisement.serializers import AdvertisementSerializer from main.serializers import PageBaseSerializer -class AdvertisementPageTypeMobileListSerializer(AdvertisementBaseSerializer): +class AdvertisementPageTypeMobileListSerializer(AdvertisementSerializer): """Serializer for AdvertisementPageTypeMobileView.""" - page = PageBaseSerializer(source='mobile_page', read_only=True) + pages = PageBaseSerializer(many=True, source='mobile_pages', read_only=True) - class Meta(AdvertisementBaseSerializer.Meta): + class Meta(AdvertisementSerializer.Meta): """Meta class.""" - fields = AdvertisementBaseSerializer.Meta.fields + [ - 'page', + fields = AdvertisementSerializer.Meta.fields + [ + 'pages', ] diff --git a/apps/advertisement/serializers/web.py b/apps/advertisement/serializers/web.py index 175f1875..a78c1f53 100644 --- a/apps/advertisement/serializers/web.py +++ b/apps/advertisement/serializers/web.py @@ -1,15 +1,15 @@ """Serializers for web app advertisements""" -from advertisement.serializers import AdvertisementBaseSerializer +from advertisement.serializers import AdvertisementSerializer from main.serializers import PageBaseSerializer -class AdvertisementPageTypeWebListSerializer(AdvertisementBaseSerializer): +class AdvertisementPageTypeWebListSerializer(AdvertisementSerializer): """Serializer for AdvertisementPageTypeWebView.""" - page = PageBaseSerializer(source='web_page', read_only=True) + pages = PageBaseSerializer(many=True, source='web_pages', read_only=True) - class Meta(AdvertisementBaseSerializer.Meta): + class Meta(AdvertisementSerializer.Meta): """Meta class.""" - fields = AdvertisementBaseSerializer.Meta.fields + [ - 'page', + fields = AdvertisementSerializer.Meta.fields + [ + 'pages', ] diff --git a/apps/advertisement/urls/back.py b/apps/advertisement/urls/back.py index 2502da0d..7a5cb133 100644 --- a/apps/advertisement/urls/back.py +++ b/apps/advertisement/urls/back.py @@ -9,10 +9,10 @@ app_name = 'advertisements' urlpatterns = [ path('', views.AdvertisementListCreateView.as_view(), name='list-create'), path('/', views.AdvertisementRUDView.as_view(), name='rud'), - path('/pages/', views.AdvertisementPageListCreateView.as_view(), - name='page-list-create'), - path('/pages//', views.AdvertisementPageRUDView.as_view(), - name='page-rud') + path('/pages/', views.AdvertisementPageCreateView.as_view(), + name='ad-page-create'), + path('/pages//', views.AdvertisementPageUDView.as_view(), + name='ad-page-update-destroy') ] urlpatterns += common_urlpatterns diff --git a/apps/advertisement/views/back.py b/apps/advertisement/views/back.py index a2973589..27a016a2 100644 --- a/apps/advertisement/views/back.py +++ b/apps/advertisement/views/back.py @@ -1,19 +1,19 @@ """Back office views for app advertisement""" -from rest_framework import generics +from rest_framework import generics, status +from rest_framework.response import Response from rest_framework import permissions from django.shortcuts import get_object_or_404 +from main.serializers import PageExtendedSerializer from advertisement.models import Advertisement -from rest_framework.response import Response -from rest_framework import status from advertisement.serializers import (AdvertisementBaseSerializer, - AdvertisementPageBaseSerializer, - AdvertisementPageListCreateSerializer) + AdvertisementDetailSerializer) class AdvertisementBackOfficeViewMixin(generics.GenericAPIView): """Base back office advertisement view.""" + pagination_class = None permission_classes = (permissions.IsAuthenticated, ) def get_queryset(self): @@ -31,14 +31,14 @@ class AdvertisementRUDView(AdvertisementBackOfficeViewMixin, generics.RetrieveUpdateDestroyAPIView): """Retrieve|Update|Destroy advertisement page view.""" - serializer_class = AdvertisementBaseSerializer + serializer_class = AdvertisementDetailSerializer -class AdvertisementPageListCreateView(AdvertisementBackOfficeViewMixin, - generics.ListCreateAPIView): - """Retrieve|Update|Destroy advertisement page view.""" +class AdvertisementPageCreateView(AdvertisementBackOfficeViewMixin, + generics.CreateAPIView): + """Create advertisement page view.""" - serializer_class = AdvertisementPageListCreateSerializer + serializer_class = PageExtendedSerializer def get_object(self): """Returns the object the view is displaying.""" @@ -56,12 +56,19 @@ class AdvertisementPageListCreateView(AdvertisementBackOfficeViewMixin, """Overridden get_queryset method.""" return self.get_object().pages.all() + def create(self, request, *args, **kwargs): + """Overridden create method.""" + request.data.update({'advertisement': self.get_object().pk}) + super().create(request, *args, **kwargs) + return Response(status=status.HTTP_200_OK) -class AdvertisementPageRUDView(AdvertisementBackOfficeViewMixin, - generics.RetrieveUpdateDestroyAPIView): - """Create|Retrieve|Update|Destroy advertisement page view.""" - serializer_class = AdvertisementPageBaseSerializer +class AdvertisementPageUDView(AdvertisementBackOfficeViewMixin, + generics.UpdateAPIView, + generics.DestroyAPIView): + """Update|Destroy advertisement page view.""" + + serializer_class = PageExtendedSerializer def get_object(self): """Returns the object the view is displaying.""" diff --git a/apps/advertisement/views/common.py b/apps/advertisement/views/common.py index 02c61873..12702d4b 100644 --- a/apps/advertisement/views/common.py +++ b/apps/advertisement/views/common.py @@ -3,8 +3,7 @@ from rest_framework import generics from rest_framework import permissions from advertisement.models import Advertisement -from advertisement.serializers import AdvertisementBaseSerializer, \ - AdvertisementPageTypeCommonListSerializer +from advertisement.serializers import AdvertisementBaseSerializer class AdvertisementBaseView(generics.GenericAPIView): @@ -16,8 +15,7 @@ class AdvertisementBaseView(generics.GenericAPIView): def get_queryset(self): """Overridden get queryset method.""" - return Advertisement.objects.with_base_related() \ - .by_locale(self.request.locale) + return Advertisement.objects.with_base_related() class AdvertisementPageTypeListView(AdvertisementBaseView, generics.ListAPIView): diff --git a/apps/main/admin.py b/apps/main/admin.py index 4b7038e7..315d1c2b 100644 --- a/apps/main/admin.py +++ b/apps/main/admin.py @@ -51,3 +51,6 @@ class PageTypeAdmin(admin.ModelAdmin): @admin.register(models.Page) class PageAdmin(admin.ModelAdmin): """Page admin.""" + list_display = ('id', '__str__', 'advertisement') + list_filter = ('advertisement__url', 'source') + date_hierarchy = 'created' diff --git a/apps/main/migrations/0041_auto_20191211_0631.py b/apps/main/migrations/0041_auto_20191211_0631.py new file mode 100644 index 00000000..973f4afd --- /dev/null +++ b/apps/main/migrations/0041_auto_20191211_0631.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.7 on 2019-12-11 06:31 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('advertisement', '0008_auto_20191116_1135'), + ('main', '0040_footer'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='page', + unique_together={('advertisement', 'source')}, + ), + ] diff --git a/apps/main/models.py b/apps/main/models.py index 0869169e..ae4168ea 100644 --- a/apps/main/models.py +++ b/apps/main/models.py @@ -305,7 +305,7 @@ class PageQuerySet(models.QuerySet): def by_platform(self, platform: int): """Filter by platform.""" - return self.filter(source=platform) + return self.filter(source__in=[Page.ALL, platform]) class Page(URLImageMixin, PlatformMixin, ProjectBaseMixin): @@ -325,6 +325,7 @@ class Page(URLImageMixin, PlatformMixin, ProjectBaseMixin): """Meta class.""" verbose_name = _('page') verbose_name_plural = _('pages') + unique_together = ('advertisement', 'source') def __str__(self): """Overridden dunder method.""" diff --git a/apps/main/serializers.py b/apps/main/serializers.py index 033da976..d586d71a 100644 --- a/apps/main/serializers.py +++ b/apps/main/serializers.py @@ -152,8 +152,6 @@ class SiteShortSerializer(serializers.ModelSerializer): ] - - class AwardBaseSerializer(serializers.ModelSerializer): """Award base serializer.""" @@ -234,10 +232,26 @@ class PageBaseSerializer(serializers.ModelSerializer): 'advertisement', ] extra_kwargs = { - 'establishment': {'write_only': True} + 'advertisement': {'write_only': True}, + 'image_url': {'required': True}, + 'width': {'required': True}, + 'height': {'required': True}, } +class PageExtendedSerializer(PageBaseSerializer): + """Extended serializer for model Page.""" + source_display = serializers.CharField(read_only=True, + source='get_source_display') + + class Meta(PageBaseSerializer.Meta): + """Meta class.""" + fields = PageBaseSerializer.Meta.fields + [ + 'source', + 'source_display', + ] + + class PageTypeBaseSerializer(serializers.ModelSerializer): """Serializer fro model PageType.""" diff --git a/apps/main/urls/back.py b/apps/main/urls/back.py index a9e55311..b4e196a3 100644 --- a/apps/main/urls/back.py +++ b/apps/main/urls/back.py @@ -20,6 +20,8 @@ urlpatterns = [ name='site-feature-rud'), path('footer/', views.FooterBackView.as_view(), name='footer-list-create'), path('footer//', views.FooterRUDBackView.as_view(), name='footer-rud'), + path('page-types/', views.PageTypeListCreateView.as_view(), + name='page-types-list-create') ] diff --git a/apps/main/views/back.py b/apps/main/views/back.py index 3d73f88c..f6f987af 100644 --- a/apps/main/views/back.py +++ b/apps/main/views/back.py @@ -4,7 +4,7 @@ from rest_framework import generics, permissions from main import serializers from main.filters import AwardFilter -from main.models import Award, Footer +from main.models import Award, Footer, PageType from main.views import SiteSettingsView, SiteListView @@ -81,3 +81,11 @@ class FooterRUDBackView(generics.RetrieveUpdateDestroyAPIView): permission_classes = (permissions.IsAuthenticatedOrReadOnly,) serializer_class = serializers.FooterBackSerializer queryset = Footer.objects.all() + + +class PageTypeListCreateView(generics.ListCreateAPIView): + """PageType back office view.""" + permission_classes = (permissions.IsAuthenticatedOrReadOnly, ) + pagination_class = None + serializer_class = serializers.PageTypeBaseSerializer + queryset = PageType.objects.all() From 19c42ab1d7f39c87ea37e1ade639b4d9c567197c Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 13:03:31 +0300 Subject: [PATCH 08/15] 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) From 822b18e2f40b1e6c27525fcf94dd5db24b0cf19c Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 11 Dec 2019 14:58:31 +0300 Subject: [PATCH 09/15] create new image after crop --- apps/gallery/serializers.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/gallery/serializers.py b/apps/gallery/serializers.py index 36360180..0aa4389f 100644 --- a/apps/gallery/serializers.py +++ b/apps/gallery/serializers.py @@ -1,8 +1,9 @@ from django.conf import settings from django.core.validators import MinValueValidator, MaxValueValidator +from django.core.files.base import ContentFile from rest_framework import serializers -from sorl.thumbnail.parsers import parse_crop -from sorl.thumbnail.parsers import ThumbnailParseError +from sorl.thumbnail import get_thumbnail +from sorl.thumbnail.parsers import parse_crop, ThumbnailParseError from django.utils.translation import gettext_lazy as _ from . import models @@ -88,15 +89,23 @@ class CropImageSerializer(ImageSerializer): quality = validated_data.pop('quality') crop = validated_data.pop('crop') + crop_params = { + 'geometry': f'{width}x{height}', + 'quality': quality, + 'crop': crop, + } + cropped_image = self._image.get_cropped_image(**crop_params) image = self._image + image.pk = None + crop_params['geometry_string'] = crop_params.pop('geometry') + resized = get_thumbnail(self._image.image, **crop_params) + image.image.save(resized.name, ContentFile(resized.read()), True) + image.save() if image and width and height: setattr(image, 'cropped_image', - image.get_cropped_image( - geometry=f'{width}x{height}', - quality=quality, - crop=crop)) + cropped_image) return image @property From 165509bc642d6bf1beac648ddc450abfc09386d9 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 11 Dec 2019 15:13:06 +0300 Subject: [PATCH 10/15] update news_gallery model --- apps/news/serializers.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/news/serializers.py b/apps/news/serializers.py index f22c7129..b45bfa3f 100644 --- a/apps/news/serializers.py +++ b/apps/news/serializers.py @@ -243,6 +243,15 @@ class NewsBackOfficeGallerySerializer(serializers.ModelSerializer): """Get url kwargs from request.""" return self.context.get('request').parser_context.get('kwargs') + def create(self, validated_data): + news_pk = self.get_request_kwargs().get('pk') + image_id = self.get_request_kwargs().get('image_id') + news_gallery_model = models.NewsGallery.objects.filter(image_id=image_id, news_id=news_pk).first() + if news_gallery_model: + news_gallery_model.update(**validated_data) + return news_gallery_model + return super().create(validated_data) + def validate(self, attrs): """Override validate method.""" news_pk = self.get_request_kwargs().get('pk') From 39c8f6d15294495e10a2c1723a2e0dcfd5a1d6d4 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 11 Dec 2019 15:47:08 +0300 Subject: [PATCH 11/15] remove carousel hardcode --- apps/main/views/common.py | 3 --- project/settings/base.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/apps/main/views/common.py b/apps/main/views/common.py index 674d045e..20033661 100644 --- a/apps/main/views/common.py +++ b/apps/main/views/common.py @@ -70,9 +70,6 @@ class CarouselListView(generics.ListAPIView): def get_queryset(self): country_code = self.request.country_code - if hasattr(settings, 'CAROUSEL_ITEMS') and country_code in settings.INTERNATIONAL_COUNTRY_CODES: - qs = models.Carousel.objects.filter(id__in=settings.CAROUSEL_ITEMS) - return qs qs = models.Carousel.objects.is_parsed().active() if country_code: qs = qs.by_country_code(country_code) diff --git a/project/settings/base.py b/project/settings/base.py index 31b7b8f7..2dfe1ba1 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -516,9 +516,6 @@ PHONENUMBER_DEFAULT_REGION = "FR" FALLBACK_LOCALE = 'en-GB' -# TMP TODO remove it later -# Временный хардкод для демонстрации > 15 ноября, потом удалить! -CAROUSEL_ITEMS = [465] ESTABLISHMENT_CHOSEN_TAGS = ['gastronomic', 'en_vogue', 'terrace', 'streetfood', 'business', 'bar_cocktail', 'brunch', 'pop'] NEWS_CHOSEN_TAGS = ['eat', 'drink', 'cook', 'style', 'international', 'event', 'partnership'] INTERNATIONAL_COUNTRY_CODES = ['www', 'main', 'next'] From f0709fa409fc029d2ef1191ef7b4ff746b882c8b Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 16:16:08 +0300 Subject: [PATCH 12/15] Fixed tag filter type --- apps/tag/views.py | 77 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/apps/tag/views.py b/apps/tag/views.py index db3970e5..dad2582f 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -78,9 +78,26 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): result_list = serializer.data query_params = request.query_params - params_type = query_params['type'] + params_type = query_params.get('type') - if params_type == 'restaurant' and 'toque_number__in' in query_params: + week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") + flags = ('toque_number', 'wine_region', 'works_noon', 'works_evening', 'works_now') + filter_flags = {flag_name: False for flag_name in flags} + additional_flags = [] + + if params_type == 'restaurant': + additional_flags += ['toque_number', 'works_noon', 'works_evening', 'works_now'] + + elif params_type == 'winery': + additional_flags += ['wine_region'] + + elif params_type == 'artisan': + additional_flags += ['works_now', 'works_at_weekday'] + + for flag_name in additional_flags: + filter_flags[flag_name] = True + + if filter_flags['toque_number']: toques = { "index_name": "toque_number", "label_translated": "Toques", @@ -93,28 +110,29 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } 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']) + if filter_flags['wine_region']: + wine_region_id = query_params.get('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)] - } + if str(wine_region_id).isdigit(): + queryset = WineRegion.objects.filter(id=int(wine_region_id)) - result_list.append(wine_regions) + else: + queryset = WineRegion.objects.all() - except ValueError: - pass + 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 queryset] + } - if params_type == 'restaurant' and 'works_noon__in' in query_params: - week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") + result_list.append(wine_regions) + + if filter_flags['works_noon']: works_noon = { "index_name": "works_noon", "label_translated": "Open noon", @@ -127,8 +145,8 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } 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") + if filter_flags['works_evening']: + works_evening = { "index_name": "works_evening", "label_translated": "Open evening", @@ -141,7 +159,7 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } result_list.append(works_evening) - if params_type in ('restaurant', 'artisan') and 'works_now' in query_params: + if filter_flags['works_now']: works_now = { "index_name": "open_now", "label_translated": "Open now", @@ -150,6 +168,19 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): } result_list.append(works_now) + if filter_flags['works_at_weekday']: + works_at_weekday = { + "index_name": "works_at_weekday", + "label_translated": "Works at weekday", + "param_name": "works_at_weekday__in", + "filters": [{ + "id": weekday, + "index_name": week_days[weekday].lower(), + "label_translated": week_days[weekday] + } for weekday in range(7)] + } + result_list.append(works_at_weekday) + if 'tags_id__in' in query_params: # filtering by params_type and tags id # todo: result_list.append( filtering_data ) From d8e3ad0bb5179c87d3afb85985de7b06ae8c02e1 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 16:21:30 +0300 Subject: [PATCH 13/15] Added works_at_weekday --- apps/tag/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tag/views.py b/apps/tag/views.py index dad2582f..75472fff 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -81,7 +81,7 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): params_type = query_params.get('type') week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") - flags = ('toque_number', 'wine_region', 'works_noon', 'works_evening', 'works_now') + flags = ('toque_number', 'wine_region', 'works_noon', 'works_evening', 'works_now', 'works_at_weekday') filter_flags = {flag_name: False for flag_name in flags} additional_flags = [] From 9f27b0c5d9e8246ae65b644ff724191fcdab615d Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 16:27:18 +0300 Subject: [PATCH 14/15] Added different types --- apps/tag/views.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/tag/views.py b/apps/tag/views.py index 75472fff..d506e23f 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -79,6 +79,10 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): query_params = request.query_params params_type = query_params.get('type') + if query_params.get('establishment_type'): + params_type = query_params.get('establishment_type') + elif query_params.get('product_type'): + params_type = query_params.get('product_type') week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") flags = ('toque_number', 'wine_region', 'works_noon', 'works_evening', 'works_now', 'works_at_weekday') @@ -97,6 +101,8 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): for flag_name in additional_flags: filter_flags[flag_name] = True + print(filter_flags) + if filter_flags['toque_number']: toques = { "index_name": "toque_number", From 0b1b960108b970c02562e15da1bf5e5a14b79ec5 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 16:27:52 +0300 Subject: [PATCH 15/15] Remove excess output --- apps/tag/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/tag/views.py b/apps/tag/views.py index d506e23f..e56447bc 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -101,8 +101,6 @@ class FiltersTagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): for flag_name in additional_flags: filter_flags[flag_name] = True - print(filter_flags) - if filter_flags['toque_number']: toques = { "index_name": "toque_number",