From 88b190d76db506d76f47a8259e5dc1501b101816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Fri, 6 Dec 2019 09:45:38 +0300 Subject: [PATCH 01/14] winery choice --- apps/account/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/account/models.py b/apps/account/models.py index 205171d0..53163d95 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -33,7 +33,7 @@ class Role(ProjectBaseMixin): REVIEWER_MANGER = 6 RESTAURANT_REVIEWER = 7 SALES_MAN = 8 - WINERY_REVIEWER = 9 + WINERY_REVIEWER = 9 # Establishments subtype "winery" SELLER = 10 ROLE_CHOICES = ( From 8c8acd3e191ccd93a4cdbf3dcc722775d81e0f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Fri, 6 Dec 2019 11:13:07 +0300 Subject: [PATCH 02/14] Models --- .../0024_role_establishment_subtype.py | 20 +++++++++++++++++++ apps/account/models.py | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 apps/account/migrations/0024_role_establishment_subtype.py diff --git a/apps/account/migrations/0024_role_establishment_subtype.py b/apps/account/migrations/0024_role_establishment_subtype.py new file mode 100644 index 00000000..3b9062c5 --- /dev/null +++ b/apps/account/migrations/0024_role_establishment_subtype.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.7 on 2019-12-06 06:55 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0067_auto_20191122_1244'), + ('account', '0023_auto_20191204_0916'), + ] + + operations = [ + migrations.AddField( + model_name='role', + name='establishment_subtype', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='establishment.EstablishmentSubType', verbose_name='Establishment subtype'), + ), + ] diff --git a/apps/account/models.py b/apps/account/models.py index 53163d95..8f6c6233 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -1,5 +1,6 @@ """Account models""" from datetime import datetime +from tabnanny import verbose from django.conf import settings from django.contrib.auth.models import AbstractUser, UserManager as BaseUserManager @@ -15,7 +16,7 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework.authtoken.models import Token from authorization.models import Application -from establishment.models import Establishment +from establishment.models import Establishment, EstablishmentSubType from location.models import Country from main.models import SiteSettings from utils.models import GMTokenGenerator @@ -54,6 +55,9 @@ class Role(ProjectBaseMixin): null=True, blank=True, on_delete=models.SET_NULL) site = models.ForeignKey(SiteSettings, verbose_name=_('Site settings'), null=True, blank=True, on_delete=models.SET_NULL) + establishment_subtype = models.ForeignKey(EstablishmentSubType, + verbose_name=_('Establishment subtype'), + null=True, blank=True, on_delete=models.SET_NULL) class UserManager(BaseUserManager): From e824b5ee65cc85e626e64073eb3a9f26998b94b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Fri, 6 Dec 2019 16:51:57 +0300 Subject: [PATCH 03/14] winery permission --- apps/establishment/models.py | 19 ----------- apps/establishment/tests.py | 57 ++++++++++++++++++++++++++++++-- apps/establishment/views/back.py | 28 ++++++++-------- apps/utils/permissions.py | 52 ++++++++++++++++++++++++++--- 4 files changed, 116 insertions(+), 40 deletions(-) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 3cdef691..20db3710 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -824,25 +824,6 @@ class ContactEmail(models.Model): return f'{self.email}' -# -# class Wine(TranslatedFieldsMixin, models.Model): -# """Wine model.""" -# establishment = models.ForeignKey( -# 'establishment.Establishment', verbose_name=_('establishment'), -# on_delete=models.CASCADE) -# bottles = models.IntegerField(_('bottles')) -# price_min = models.DecimalField( -# _('price min'), max_digits=14, decimal_places=2) -# price_max = models.DecimalField( -# _('price max'), max_digits=14, decimal_places=2) -# by_glass = models.BooleanField(_('by glass')) -# price_glass_min = models.DecimalField( -# _('price min'), max_digits=14, decimal_places=2) -# price_glass_max = models.DecimalField( -# _('price max'), max_digits=14, decimal_places=2) -# - - class Plate(TranslatedFieldsMixin, models.Model): """Plate model.""" STR_FIELD_NAME = 'name' diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index bd96b052..86606d6b 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -4,7 +4,8 @@ from account.models import User from rest_framework import status from http.cookies import SimpleCookie from main.models import Currency -from establishment.models import Establishment, EstablishmentType, Menu, SocialChoice, SocialNetwork +from establishment.models import Establishment, EstablishmentType, EstablishmentSubType,\ + Menu, SocialChoice, SocialNetwork # Create your tests here. from translation.models import Language from account.models import Role, UserRole @@ -87,7 +88,59 @@ class BaseTestCase(APITestCase): ) -class EstablishmentBTests(BaseTestCase): +class WineryBackTests(BaseTestCase): + def setUp(self): + super().setUp() + self.user_role.delete() + self.role.delete() + + def test_establishment_CRUD(self): + params = {'page': 1, 'page_size': 1, } + response = self.client.get('/api/back/establishments/', params, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.establishment_subtype = EstablishmentSubType.objects.create( + name={"en-GB":"some text"}, + index_name='Index name', + establishment_type_id=self.establishment_type.id + ) + + self.establishment_subtype.save() + self.role = Role.objects.create(role=Role.WINERY_REVIEWER, + establishment_subtype_id=self.establishment_subtype.id) + self.role.save() + self.establishment.add_establishment_subtype(self.establishment_subtype) + + data = { + 'name': 'Test establishment', + 'type_id': self.establishment_type.id, + 'is_publish': True, + 'slug': 'test-establishment-slug', + 'tz': py_tz('Europe/Moscow').zone, + 'address_id': self.address.id + } + + response = self.client.post('/api/back/establishments/', data=data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get(f'/api/back/establishments/{self.establishment.id}/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + update_data = { + 'name': 'Test new establishment' + } + + response = self.client.patch(f'/api/back/establishments/{self.establishment.id}/', + data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/', + format='json') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + + +class EstablishmentBackTests(BaseTestCase): def test_establishment_CRUD(self): params = {'page': 1, 'page_size': 1, } response = self.client.get('/api/back/establishments/', params, format='json') diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index 6fa4d821..e7cd8f73 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -3,10 +3,9 @@ from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404 from rest_framework import generics, permissions, status -from utils.permissions import IsCountryAdmin, IsEstablishmentManager from establishment import filters, models, serializers from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer -from utils.permissions import IsCountryAdmin, IsEstablishmentManager +from utils.permissions import IsCountryAdmin, IsEstablishmentManager, IsWineryReviewer from utils.views import CreateDestroyGalleryViewMixin from timetable.models import Timetable from rest_framework import status @@ -25,7 +24,8 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP """Establishment list/create view.""" filter_class = filters.EstablishmentFilter - permission_classes = [IsCountryAdmin | IsEstablishmentManager] + + permission_classes = [IsWineryReviewer | IsCountryAdmin | IsEstablishmentManager] queryset = models.Establishment.objects.all() serializer_class = serializers.EstablishmentListCreateSerializer @@ -33,13 +33,13 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView): queryset = models.Establishment.objects.all() serializer_class = serializers.EstablishmentRUDSerializer - permission_classes = [IsCountryAdmin | IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsCountryAdmin | IsEstablishmentManager] class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView): """Establishment schedule RUD view""" serializer_class = ScheduleRUDSerializer - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer |IsEstablishmentManager] def get_object(self): """ @@ -64,21 +64,21 @@ class EstablishmentScheduleCreateView(generics.CreateAPIView): """Establishment schedule Create view""" serializer_class = ScheduleCreateSerializer queryset = Timetable.objects.all() - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class MenuListCreateView(generics.ListCreateAPIView): """Menu list create view.""" serializer_class = serializers.MenuSerializers queryset = models.Menu.objects.all() - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class MenuRUDView(generics.RetrieveUpdateDestroyAPIView): """Menu RUD view.""" serializer_class = serializers.MenuRUDSerializers queryset = models.Menu.objects.all() - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class SocialChoiceListCreateView(generics.ListCreateAPIView): @@ -116,14 +116,14 @@ class PlateListCreateView(generics.ListCreateAPIView): serializer_class = serializers.PlatesSerializers queryset = models.Plate.objects.all() pagination_class = None - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class PlateRUDView(generics.RetrieveUpdateDestroyAPIView): """Plate RUD view.""" serializer_class = serializers.PlatesSerializers queryset = models.Plate.objects.all() - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class PhonesListCreateView(generics.ListCreateAPIView): @@ -131,14 +131,14 @@ class PhonesListCreateView(generics.ListCreateAPIView): serializer_class = serializers.ContactPhoneBackSerializers queryset = models.ContactPhone.objects.all() pagination_class = None - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class PhonesRUDView(generics.RetrieveUpdateDestroyAPIView): """Phones RUD view.""" serializer_class = serializers.ContactPhoneBackSerializers queryset = models.ContactPhone.objects.all() - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class EmailListCreateView(generics.ListCreateAPIView): @@ -146,14 +146,14 @@ class EmailListCreateView(generics.ListCreateAPIView): serializer_class = serializers.ContactEmailBackSerializers queryset = models.ContactEmail.objects.all() pagination_class = None - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class EmailRUDView(generics.RetrieveUpdateDestroyAPIView): """Email RUD view.""" serializer_class = serializers.ContactEmailBackSerializers queryset = models.ContactEmail.objects.all() - permission_classes = [IsEstablishmentManager] + permission_classes = [IsWineryReviewer | IsEstablishmentManager] class EmployeeListCreateView(generics.ListCreateAPIView): diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 30055c44..432c653b 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -7,7 +7,8 @@ from rest_framework_simplejwt.tokens import AccessToken from account.models import UserRole, Role from authorization.models import JWTRefreshToken from utils.tokens import GMRefreshToken - +from establishment.models import EstablishmentSubType +from location.models import Address class IsAuthenticatedAndTokenIsValid(permissions.BasePermission): """ @@ -56,8 +57,9 @@ class IsGuest(permissions.IsAuthenticatedOrReadOnly): """ Object-level permission to only allow owners of an object to edit it. """ - + SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS') def has_permission(self, request, view): + rules = [ request.user.is_superuser, request.method in permissions.SAFE_METHODS @@ -306,7 +308,6 @@ class IsEstablishmentManager(IsStandardUser): rules = [ # special! super().has_permission(request, view) - # super().has_object_permission(request, view, obj) ] role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \ @@ -319,7 +320,6 @@ class IsEstablishmentManager(IsStandardUser): ).exists(), # special! super().has_permission(request, view) - # super().has_object_permission(request, view, obj) ] return any(rules) @@ -368,7 +368,7 @@ class IsRestaurantReviewer(IsStandardUser): # and request.user.email_confirmed, if hasattr(request.data, 'user') and hasattr(request.data, 'object_id'): role = Role.objects.filter(role=Role.RESTAURANT_REVIEWER) \ - .first() # 'Comments moderator' + .first() rules = [ UserRole.objects.filter(user=request.user, role=role, @@ -394,3 +394,45 @@ class IsRestaurantReviewer(IsStandardUser): ] return any(rules) + + +class IsWineryReviewer(IsStandardUser): + + def has_permission(self, request, view): + rules = [ + super().has_permission(request, view) + ] + + if 'type_id' in request.data and 'address_id' in request.data and request.user: + countries = Address.objects.filter(id=request.data['address_id']) + + est = EstablishmentSubType.objects.filter(establishment_type_id=request.data['type_id']) + if est.exists(): + role = Role.objects.filter(establishment_subtype_id__in=[type.id for type in est], + role=Role.WINERY_REVIEWER, + country_id__in=[country.id for country in countries]) \ + .first() + + rules.append( + UserRole.objects.filter(user=request.user, role=role).exists() + ) + + return any(rules) + + def has_object_permission(self, request, view, obj): + rules = [ + super().has_object_permission(request, view, obj) + ] + if hasattr(obj, 'type_id'): + est = EstablishmentSubType.objects.filter(establishment_type_id=obj.type_id) + role = Role.objects.filter(role=Role.WINERY_REVIEWER, + establishment_subtype_id__in=[id for type.id in est], + country_id=obj.country_id).first() + + rules = [ + UserRole.objects.filter(user=request.user, role=role, + establishment_id=obj.object_id + ).exists(), + super().has_object_permission(request, view, obj) + ] + return any(rules) \ No newline at end of file From af7aef6d233408cad387a4e319328ec06c374f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Mon, 9 Dec 2019 09:38:18 +0300 Subject: [PATCH 04/14] Add winery reviewer --- apps/utils/permissions.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 432c653b..0d21c096 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -423,15 +423,28 @@ class IsWineryReviewer(IsStandardUser): rules = [ super().has_object_permission(request, view, obj) ] - if hasattr(obj, 'type_id'): - est = EstablishmentSubType.objects.filter(establishment_type_id=obj.type_id) + # AttributeError: 'Establishment' object has no attribute 'object_id' + if hasattr(obj, 'type_id') or hasattr(obj, 'establishment_type_id'): + type_id: int + if hasattr(obj, 'type_id'): + type_id = obj.type_id + else: + type_id = obj.establishment_type_id + + est = EstablishmentSubType.objects.filter(establishment_type_id=type_id) role = Role.objects.filter(role=Role.WINERY_REVIEWER, establishment_subtype_id__in=[id for type.id in est], country_id=obj.country_id).first() + object_id: int + if hasattr(obj, 'object_id'): + object_id = obj.object_id + else: + object_id = obj.establishment_id + rules = [ UserRole.objects.filter(user=request.user, role=role, - establishment_id=obj.object_id + establishment_id=object_id ).exists(), super().has_object_permission(request, view, obj) ] From 5cac9659e5d54ebcdfde01aab85c927d65e1dfb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Mon, 9 Dec 2019 09:38:58 +0300 Subject: [PATCH 05/14] Clean code --- apps/utils/permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 0d21c096..498f5932 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -423,7 +423,7 @@ class IsWineryReviewer(IsStandardUser): rules = [ super().has_object_permission(request, view, obj) ] - # AttributeError: 'Establishment' object has no attribute 'object_id' + if hasattr(obj, 'type_id') or hasattr(obj, 'establishment_type_id'): type_id: int if hasattr(obj, 'type_id'): From 38839f75f9d63da93cf15ba69823858978561149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Mon, 9 Dec 2019 09:59:17 +0300 Subject: [PATCH 06/14] Fix account test --- apps/account/serializers/back.py | 1 + apps/account/urls/back.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/account/serializers/back.py b/apps/account/serializers/back.py index 699210e7..15e0684e 100644 --- a/apps/account/serializers/back.py +++ b/apps/account/serializers/back.py @@ -33,6 +33,7 @@ class BackUserSerializer(serializers.ModelSerializer): 'email_confirmed', 'newsletter', 'roles', + 'password' ) extra_kwargs = { 'password': {'write_only': True} diff --git a/apps/account/urls/back.py b/apps/account/urls/back.py index 630a4cb9..30f21573 100644 --- a/apps/account/urls/back.py +++ b/apps/account/urls/back.py @@ -8,6 +8,6 @@ app_name = 'account' urlpatterns = [ path('role/', views.RoleLstView.as_view(), name='role-list-create'), path('user-role/', views.UserRoleLstView.as_view(), name='user-role-list-create'), - path('user/', views.UserLstView.as_view(), name='user-list-create'), + path('user/', views.UserLstView.as_view(), name='user-create-list'), path('user//', views.UserRUDView.as_view(), name='user-rud'), ] From dc7a6a911aadc1156fe8867ba462eab708164db7 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Mon, 9 Dec 2019 14:29:54 +0300 Subject: [PATCH 07/14] refactoring --- apps/advertisement/models.py | 4 ++++ apps/advertisement/serializers/common.py | 5 ----- apps/advertisement/views/common.py | 5 ++++- apps/advertisement/views/web.py | 1 + 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/advertisement/models.py b/apps/advertisement/models.py index 920e3389..66cd0024 100644 --- a/apps/advertisement/models.py +++ b/apps/advertisement/models.py @@ -22,6 +22,10 @@ class AdvertisementQuerySet(models.QuerySet): """Filter Advertisement by page type.""" return self.filter(page_type__name=page_type) + def by_country(self, code: str): + """Filter Advertisement by country code.""" + return self.filter(sites__country__code=code) + def by_locale(self, locale): """Filter by locale.""" return self.filter(target_languages__locale=locale) diff --git a/apps/advertisement/serializers/common.py b/apps/advertisement/serializers/common.py index 0adb74f9..9caee0c2 100644 --- a/apps/advertisement/serializers/common.py +++ b/apps/advertisement/serializers/common.py @@ -11,14 +11,11 @@ from main.models import SiteSettings class AdvertisementBaseSerializer(serializers.ModelSerializer): """Base serializer for model Advertisement.""" - languages = LanguageSerializer(many=True, read_only=True, - source='target_languages') target_languages = serializers.PrimaryKeyRelatedField( queryset=Language.objects.all(), many=True, write_only=True ) - sites = SiteShortSerializer(many=True, read_only=True) target_sites = serializers.PrimaryKeyRelatedField( queryset=SiteSettings.objects.all(), many=True, @@ -33,9 +30,7 @@ class AdvertisementBaseSerializer(serializers.ModelSerializer): 'uuid', 'url', 'block_level', - 'languages', 'target_languages', - 'sites', 'target_sites', 'start', 'end', diff --git a/apps/advertisement/views/common.py b/apps/advertisement/views/common.py index 43c6e965..02c61873 100644 --- a/apps/advertisement/views/common.py +++ b/apps/advertisement/views/common.py @@ -28,5 +28,8 @@ class AdvertisementPageTypeListView(AdvertisementBaseView, generics.ListAPIView) product_type = self.kwargs.get('page_type') qs = super(AdvertisementPageTypeListView, self).get_queryset() if product_type: - return qs.by_page_type(product_type) + return qs.by_page_type(product_type) \ + .by_country(self.request.country_code) \ + .by_locale(self.request.locale) \ + .distinct('id') return qs.none() diff --git a/apps/advertisement/views/web.py b/apps/advertisement/views/web.py index db1cfde8..a9e527a0 100644 --- a/apps/advertisement/views/web.py +++ b/apps/advertisement/views/web.py @@ -7,3 +7,4 @@ class AdvertisementPageTypeWebListView(AdvertisementPageTypeListView): """Advertisement mobile list view.""" serializer_class = AdvertisementPageTypeWebListSerializer + From ea760fc674784e520e16501ac7b0d19d43d7f7ae Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 9 Dec 2019 15:00:15 +0300 Subject: [PATCH 08/14] rename attrs --- apps/search_indexes/serializers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/search_indexes/serializers.py b/apps/search_indexes/serializers.py index a43ebaf7..3b5561fa 100644 --- a/apps/search_indexes/serializers.py +++ b/apps/search_indexes/serializers.py @@ -243,8 +243,8 @@ class WineOriginSerializer(serializers.Serializer): class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer): """Establishment document serializer.""" - establishment_type = EstablishmentTypeSerializer() - establishment_subtypes = EstablishmentTypeSerializer(many=True) + type = EstablishmentTypeSerializer(source='establishment_type') + subtypes = EstablishmentTypeSerializer(many=True, source='establishment_subtypes') address = AddressDocumentSerializer(allow_null=True) tags = TagsDocumentSerializer(many=True, source='visible_tags') restaurant_category = TagsDocumentSerializer(many=True, allow_null=True) @@ -280,8 +280,8 @@ class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer): 'wine_origins', # 'works_now', # 'collections', - # 'establishment_type', - # 'establishment_subtypes', + 'type', + 'subtypes', ) From 912431690d5c12384542c5834b5df3c4b05d89cd Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 9 Dec 2019 15:21:39 +0300 Subject: [PATCH 09/14] rename attrs #2 --- apps/establishment/serializers/common.py | 4 ++-- apps/transfer/serializers/guide.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 52d7ae69..5c77ccbf 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -450,13 +450,13 @@ class EstablishmentSimilarSerializer(EstablishmentBaseSerializer): address = AddressDetailSerializer(read_only=True) schedule = ScheduleRUDSerializer(many=True, allow_null=True) - establishment_type = EstablishmentTypeGeoSerializer() + type = EstablishmentTypeGeoSerializer(source='establishment_type') artisan_category = TagBaseSerializer(many=True, allow_null=True) class Meta(EstablishmentBaseSerializer.Meta): fields = EstablishmentBaseSerializer.Meta.fields + [ 'schedule', - 'establishment_type', + 'type', 'artisan_category', ] diff --git a/apps/transfer/serializers/guide.py b/apps/transfer/serializers/guide.py index f0cddd02..8a083e55 100644 --- a/apps/transfer/serializers/guide.py +++ b/apps/transfer/serializers/guide.py @@ -68,7 +68,7 @@ class GuideSerializer(TransferSerializerMixin): class GuideFilterSerializer(TransferSerializerMixin): id = serializers.IntegerField() year = serializers.CharField(allow_null=True) - establishment_type = serializers.CharField(allow_null=True) + type = serializers.CharField(allow_null=True, source='establishment_type') countries = serializers.CharField(allow_null=True) regions = serializers.CharField(allow_null=True) subregions = serializers.CharField(allow_null=True) @@ -86,7 +86,7 @@ class GuideFilterSerializer(TransferSerializerMixin): fields = ( 'id', 'year', - 'establishment_type', + 'type', 'countries', 'regions', 'subregions', From 188f8877b485f12d205cbdbf05e87c94db4c5a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Mon, 9 Dec 2019 16:35:38 +0300 Subject: [PATCH 10/14] Fix test --- apps/establishment/tests.py | 52 ------------------------------------- 1 file changed, 52 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index c68bf029..f0c26abe 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -88,58 +88,6 @@ class BaseTestCase(APITestCase): ) -class WineryBackTests(BaseTestCase): - def setUp(self): - super().setUp() - self.user_role.delete() - self.role.delete() - - def test_establishment_CRUD(self): - params = {'page': 1, 'page_size': 1, } - response = self.client.get('/api/back/establishments/', params, format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) - - self.establishment_subtype = EstablishmentSubType.objects.create( - name={"en-GB":"some text"}, - index_name='Index name', - establishment_type_id=self.establishment_type.id - ) - - self.establishment_subtype.save() - self.role = Role.objects.create(role=Role.WINERY_REVIEWER, - establishment_subtype_id=self.establishment_subtype.id) - self.role.save() - self.establishment.add_establishment_subtype(self.establishment_subtype) - - data = { - 'name': 'Test establishment', - 'type_id': self.establishment_type.id, - 'is_publish': True, - 'slug': 'test-establishment-slug', - 'tz': py_tz('Europe/Moscow').zone, - 'address_id': self.address.id - } - - response = self.client.post('/api/back/establishments/', data=data, format='json') - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - response = self.client.get(f'/api/back/establishments/{self.establishment.id}/', format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) - - update_data = { - 'name': 'Test new establishment' - } - - response = self.client.patch(f'/api/back/establishments/{self.establishment.id}/', - data=update_data) - self.assertEqual(response.status_code, status.HTTP_200_OK) - - response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/', - format='json') - self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) - - - class EstablishmentBackTests(BaseTestCase): def test_establishment_CRUD(self): params = {'page': 1, 'page_size': 1, } From 0f11a47a790c0b49dbd9b306eaff90644d0a8431 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 9 Dec 2019 16:47:46 +0300 Subject: [PATCH 11/14] rest category & rest cuisine for favs (cherry picked from commit 79a70fb) --- apps/establishment/serializers/common.py | 6 +++++- apps/favorites/views.py | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 5c77ccbf..19b4b764 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -451,13 +451,17 @@ class EstablishmentSimilarSerializer(EstablishmentBaseSerializer): address = AddressDetailSerializer(read_only=True) schedule = ScheduleRUDSerializer(many=True, allow_null=True) type = EstablishmentTypeGeoSerializer(source='establishment_type') - artisan_category = TagBaseSerializer(many=True, allow_null=True) + artisan_category = TagBaseSerializer(many=True, allow_null=True, read_only=True) + restaurant_category = TagBaseSerializer(many=True, allow_null=True, read_only=True) + restaurant_cuisine = TagBaseSerializer(many=True, allow_null=True, read_only=True) class Meta(EstablishmentBaseSerializer.Meta): fields = EstablishmentBaseSerializer.Meta.fields + [ 'schedule', 'type', 'artisan_category', + 'restaurant_category', + 'restaurant_cuisine', ] diff --git a/apps/favorites/views.py b/apps/favorites/views.py index bee25ced..4faa3e07 100644 --- a/apps/favorites/views.py +++ b/apps/favorites/views.py @@ -30,6 +30,8 @@ class FavoritesEstablishmentListView(generics.ListAPIView): """Override get_queryset method""" return Establishment.objects.filter(favorites__user=self.request.user) \ .order_by('-favorites').with_base_related() \ + .with_certain_tag_category_related('category', 'restaurant_category') \ + .with_certain_tag_category_related('cuisine', 'restaurant_cuisine') \ .with_certain_tag_category_related('shop_category', 'artisan_category') From a6728e3148e4c5c272af33503ca778d0ea3b1a7c Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 9 Dec 2019 16:59:40 +0300 Subject: [PATCH 12/14] wine_origins for favorites establishments --- apps/product/serializers/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/product/serializers/common.py b/apps/product/serializers/common.py index d794ca93..51ff8e1e 100644 --- a/apps/product/serializers/common.py +++ b/apps/product/serializers/common.py @@ -6,7 +6,8 @@ from comment.models import Comment from comment.serializers import CommentSerializer from establishment.serializers import EstablishmentProductShortSerializer from establishment.serializers.common import _EstablishmentAddressShortSerializer -from location.serializers import WineOriginRegionBaseSerializer, WineOriginBaseSerializer +from location.serializers import WineOriginRegionBaseSerializer,\ + WineOriginBaseSerializer, EstablishmentWineOriginBaseSerializer from main.serializers import AwardSerializer from product import models from review.serializers import ReviewShortSerializer @@ -95,6 +96,7 @@ class ProductBaseSerializer(serializers.ModelSerializer): preview_image_url = serializers.URLField(allow_null=True, read_only=True) in_favorites = serializers.BooleanField(allow_null=True) + wine_origins = EstablishmentWineOriginBaseSerializer(many=True, read_only=True) class Meta: """Meta class.""" From d12ad93fe1c258631f68d317335fcfb92c54a4cb Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 9 Dec 2019 17:19:29 +0300 Subject: [PATCH 13/14] try to fix issue w/ news tag binding --- apps/search_indexes/documents/tag_category.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/search_indexes/documents/tag_category.py b/apps/search_indexes/documents/tag_category.py index ed69c8b7..3c335cdf 100644 --- a/apps/search_indexes/documents/tag_category.py +++ b/apps/search_indexes/documents/tag_category.py @@ -2,6 +2,7 @@ from django.conf import settings from django_elasticsearch_dsl import Document, Index, fields from tag import models +from news.models import News TagCategoryIndex = Index(settings.ELASTICSEARCH_INDEX_NAMES.get(__name__, 'tag_category')) TagCategoryIndex.settings(number_of_shards=2, number_of_replicas=2) @@ -26,7 +27,7 @@ class TagCategoryDocument(Document): 'public', 'value_type' ) - related_models = [models.Tag] + related_models = [models.Tag, News] def get_queryset(self): From be793eed73658727fb66da7e75b2284634247e35 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 9 Dec 2019 17:40:05 +0300 Subject: [PATCH 14/14] fix issue w/ tags binding --- apps/search_indexes/documents/tag_category.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/search_indexes/documents/tag_category.py b/apps/search_indexes/documents/tag_category.py index 3c335cdf..cd2c8a90 100644 --- a/apps/search_indexes/documents/tag_category.py +++ b/apps/search_indexes/documents/tag_category.py @@ -32,3 +32,11 @@ class TagCategoryDocument(Document): def get_queryset(self): return super().get_queryset().with_base_related() + + def get_instances_from_related(self, related_instance): + """If related_models is set, define how to retrieve the Car instance(s) from the related model. + The related_models option should be used with caution because it can lead in the index + to the updating of a lot of items. + """ + if isinstance(related_instance, News): + return related_instance.tags \ No newline at end of file