Merge branch 'develop' into feature/permission_winery
This commit is contained in:
commit
8e63b969bf
0
apps/booking/urls/__init__.py
Normal file
0
apps/booking/urls/__init__.py
Normal file
8
apps/booking/urls/mobile.py
Normal file
8
apps/booking/urls/mobile.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from booking.urls import common as common_views
|
||||
app = 'booking'
|
||||
|
||||
|
||||
urlpatterns_api = []
|
||||
|
||||
urlpatterns = urlpatterns_api + \
|
||||
common_views.urlpatterns
|
||||
8
apps/booking/urls/web.py
Normal file
8
apps/booking/urls/web.py
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
from booking.urls import common as common_views
|
||||
app = 'booking'
|
||||
|
||||
|
||||
urlpatterns_api = []
|
||||
|
||||
urlpatterns = urlpatterns_api + \
|
||||
common_views.urlpatterns
|
||||
|
|
@ -457,9 +457,15 @@ class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin,
|
|||
def visible_tags(self):
|
||||
return super().visible_tags \
|
||||
.exclude(category__index_name__in=['guide', 'collection', 'purchased_item',
|
||||
'business_tag', 'business_tags_de', 'tag'])
|
||||
'business_tag', 'business_tags_de']) \
|
||||
.exclude(value__in=['rss', 'rss_selection'])
|
||||
# todo: recalculate toque_number
|
||||
|
||||
@property
|
||||
def visible_tags_detail(self):
|
||||
"""Removes some tags from detail Establishment representation"""
|
||||
return self.visible_tags.exclude(category__index_name__in=['tag'])
|
||||
|
||||
def recalculate_toque_number(self):
|
||||
toque_number = 0
|
||||
if self.address and self.public_mark:
|
||||
|
|
|
|||
|
|
@ -232,9 +232,13 @@ class EstablishmentBackOfficeGallerySerializer(serializers.ModelSerializer):
|
|||
def validate(self, attrs):
|
||||
"""Override validate method."""
|
||||
establishment_pk = self.get_request_kwargs().get('pk')
|
||||
establishment_slug = self.get_request_kwargs().get('slug')
|
||||
|
||||
search_kwargs = {'pk': establishment_pk} if establishment_pk else {'slug': establishment_slug}
|
||||
|
||||
image_id = self.get_request_kwargs().get('image_id')
|
||||
|
||||
establishment_qs = models.Establishment.objects.filter(pk=establishment_pk)
|
||||
establishment_qs = models.Establishment.objects.filter(**search_kwargs)
|
||||
image_qs = Image.objects.filter(id=image_id)
|
||||
|
||||
if not establishment_qs.exists():
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from utils.serializers import ImageBaseSerializer, CarouselCreateSerializer
|
|||
from utils.serializers import (ProjectModelSerializer, TranslatedField,
|
||||
FavoritesCreateSerializer)
|
||||
from location.serializers import EstablishmentWineRegionBaseSerializer, \
|
||||
EstablishmentWineOriginBaseSerializer
|
||||
EstablishmentWineOriginBaseSerializer
|
||||
|
||||
|
||||
class ContactPhonesSerializer(serializers.ModelSerializer):
|
||||
|
|
@ -239,6 +239,30 @@ class EstablishmentShortSerializer(serializers.ModelSerializer):
|
|||
]
|
||||
|
||||
|
||||
class _EstablishmentAddressShortSerializer(serializers.ModelSerializer):
|
||||
"""Short serializer for establishment."""
|
||||
city = CitySerializer(source='address.city', allow_null=True)
|
||||
establishment_type = EstablishmentTypeGeoSerializer()
|
||||
establishment_subtypes = EstablishmentSubTypeBaseSerializer(many=True)
|
||||
currency = CurrencySerializer(read_only=True)
|
||||
address = AddressBaseSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = models.Establishment
|
||||
fields = [
|
||||
'id',
|
||||
'name',
|
||||
'index_name',
|
||||
'slug',
|
||||
'city',
|
||||
'establishment_type',
|
||||
'establishment_subtypes',
|
||||
'currency',
|
||||
'address',
|
||||
]
|
||||
|
||||
|
||||
class EstablishmentProductShortSerializer(serializers.ModelSerializer):
|
||||
"""SHORT Serializer for displaying info about an establishment on product page."""
|
||||
establishment_type = EstablishmentTypeGeoSerializer()
|
||||
|
|
@ -369,7 +393,7 @@ class EstablishmentDetailSerializer(EstablishmentBaseSerializer):
|
|||
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
||||
many=True)
|
||||
address = AddressDetailSerializer(read_only=True)
|
||||
|
||||
tags = TagBaseSerializer(read_only=True, many=True, source='visible_tags_detail')
|
||||
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
||||
best_price_menu = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
||||
best_price_carte = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
||||
|
|
@ -522,7 +546,9 @@ class EstablishmentCarouselCreateSerializer(CarouselCreateSerializer):
|
|||
"""Serializer to carousel object w/ model News."""
|
||||
|
||||
def validate(self, attrs):
|
||||
establishment = models.Establishment.objects.filter(pk=self.pk).first()
|
||||
search_kwargs = {'pk': self.pk} if self.pk else {'slug': self.slug}
|
||||
|
||||
establishment = models.Establishment.objects.filter(**search_kwargs).first()
|
||||
if not establishment:
|
||||
raise serializers.ValidationError({'detail': _('Object not found.')})
|
||||
|
||||
|
|
|
|||
|
|
@ -157,18 +157,18 @@ class EstablishmentBackTests(BaseTestCase):
|
|||
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')
|
||||
response = self.client.get(f'/api/back/establishments/slug/{self.establishment.slug}/', 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}/',
|
||||
response = self.client.patch(f'/api/back/establishments/slug/{self.establishment.slug}/',
|
||||
data=update_data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/',
|
||||
response = self.client.delete(f'/api/back/establishments/slug/{self.establishment.slug}/',
|
||||
format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
|
@ -425,22 +425,22 @@ class EstablishmentShedulerTests(ChildTestCase):
|
|||
'weekday': 1
|
||||
}
|
||||
|
||||
response = self.client.post(f'/api/back/establishments/{self.establishment.id}/schedule/', data=data)
|
||||
response = self.client.post(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/', data=data)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
schedule = response.data
|
||||
|
||||
response = self.client.get(f'/api/back/establishments/{self.establishment.id}/schedule/{schedule["id"]}/')
|
||||
response = self.client.get(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/{schedule["id"]}/')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
update_data = {
|
||||
'weekday': 2
|
||||
}
|
||||
|
||||
response = self.client.patch(f'/api/back/establishments/{self.establishment.id}/schedule/{schedule["id"]}/',
|
||||
response = self.client.patch(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/{schedule["id"]}/',
|
||||
data=update_data)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/schedule/{schedule["id"]}/')
|
||||
response = self.client.delete(f'/api/back/establishments/slug/{self.establishment.slug}/schedule/{schedule["id"]}/')
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
|
|
@ -537,8 +537,8 @@ class EstablishmentCarouselTests(ChildTestCase):
|
|||
"object_id": self.establishment.id
|
||||
}
|
||||
|
||||
response = self.client.post(f'/api/back/establishments/{self.establishment.id}/carousels/', data=data)
|
||||
response = self.client.post(f'/api/back/establishments/slug/{self.establishment.slug}/carousels/', data=data)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/carousels/')
|
||||
response = self.client.delete(f'/api/back/establishments/slug/{self.establishment.slug}/carousels/')
|
||||
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||
|
|
|
|||
|
|
@ -8,25 +8,25 @@ app_name = 'establishment'
|
|||
|
||||
urlpatterns = [
|
||||
path('', views.EstablishmentListCreateView.as_view(), name='list'),
|
||||
path('<int:pk>/', views.EstablishmentRUDView.as_view(), name='detail'),
|
||||
path('<int:pk>/carousels/', views.EstablishmentCarouselCreateDestroyView.as_view(),
|
||||
path('slug/<slug:slug>/', views.EstablishmentRUDView.as_view(), name='detail'),
|
||||
path('slug/<slug:slug>/carousels/', views.EstablishmentCarouselCreateDestroyView.as_view(),
|
||||
name='create-destroy-carousels'),
|
||||
path('<int:pk>/schedule/<int:schedule_id>/', views.EstablishmentScheduleRUDView.as_view(),
|
||||
path('slug/<slug:slug>/schedule/<int:schedule_id>/', views.EstablishmentScheduleRUDView.as_view(),
|
||||
name='schedule-rud'),
|
||||
path('<int:pk>/schedule/', views.EstablishmentScheduleCreateView.as_view(),
|
||||
path('slug/<slug:slug>/schedule/', views.EstablishmentScheduleCreateView.as_view(),
|
||||
name='schedule-create'),
|
||||
path('<int:pk>/gallery/', views.EstablishmentGalleryListView.as_view(),
|
||||
path('slug/<slug:slug>/gallery/', views.EstablishmentGalleryListView.as_view(),
|
||||
name='gallery-list'),
|
||||
path('<int:pk>/gallery/<int:image_id>/',
|
||||
path('slug/<slug:slug>/gallery/<int:image_id>/',
|
||||
views.EstablishmentGalleryCreateDestroyView.as_view(),
|
||||
name='gallery-create-destroy'),
|
||||
path('<int:pk>/companies/', views.EstablishmentCompanyListCreateView.as_view(),
|
||||
path('slug/<slug:slug>/companies/', views.EstablishmentCompanyListCreateView.as_view(),
|
||||
name='company-list-create'),
|
||||
path('<int:pk>/companies/<int:company_pk>/', views.EstablishmentCompanyRUDView.as_view(),
|
||||
path('slug/<slug:slug>/companies/<int:company_pk>/', views.EstablishmentCompanyRUDView.as_view(),
|
||||
name='company-rud'),
|
||||
path('<int:pk>/notes/', views.EstablishmentNoteListCreateView.as_view(),
|
||||
path('slug/<slug:slug>/notes/', views.EstablishmentNoteListCreateView.as_view(),
|
||||
name='note-list-create'),
|
||||
path('<int:pk>/notes/<int:note_pk>/', views.EstablishmentNoteRUDView.as_view(),
|
||||
path('slug/<slug:slug>/notes/<int:note_pk>/', views.EstablishmentNoteRUDView.as_view(),
|
||||
name='note-rud'),
|
||||
path('menus/', views.MenuListCreateView.as_view(), name='menu-list'),
|
||||
path('menus/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP
|
|||
|
||||
|
||||
class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
lookup_field = 'slug'
|
||||
queryset = models.Establishment.objects.all()
|
||||
serializer_class = serializers.EstablishmentRUDSerializer
|
||||
permission_classes = [IsWineryReviewer | IsCountryAdmin | IsEstablishmentManager]
|
||||
|
|
@ -38,6 +39,7 @@ class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
|
||||
class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Establishment schedule RUD view"""
|
||||
lookup_field = 'slug'
|
||||
serializer_class = ScheduleRUDSerializer
|
||||
permission_classes = [IsWineryReviewer |IsEstablishmentManager]
|
||||
|
||||
|
|
@ -45,11 +47,11 @@ class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
"""
|
||||
Returns the object the view is displaying.
|
||||
"""
|
||||
establishment_pk = self.kwargs['pk']
|
||||
establishment_slug = self.kwargs['slug']
|
||||
schedule_id = self.kwargs['schedule_id']
|
||||
|
||||
establishment = get_object_or_404(klass=models.Establishment.objects.all(),
|
||||
pk=establishment_pk)
|
||||
slug=establishment_slug)
|
||||
schedule = get_object_or_404(klass=establishment.schedule,
|
||||
id=schedule_id)
|
||||
|
||||
|
|
@ -62,6 +64,7 @@ class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
|
||||
class EstablishmentScheduleCreateView(generics.CreateAPIView):
|
||||
"""Establishment schedule Create view"""
|
||||
lookup_field = 'slug'
|
||||
serializer_class = ScheduleCreateSerializer
|
||||
queryset = Timetable.objects.all()
|
||||
permission_classes = [IsWineryReviewer | IsEstablishmentManager]
|
||||
|
|
@ -210,6 +213,7 @@ class EstablishmentSubtypeRUDView(generics.RetrieveUpdateDestroyAPIView):
|
|||
class EstablishmentGalleryCreateDestroyView(EstablishmentMixinViews,
|
||||
CreateDestroyGalleryViewMixin):
|
||||
"""Resource for a create|destroy gallery for establishment for back-office users."""
|
||||
lookup_field = 'slug'
|
||||
serializer_class = serializers.EstablishmentBackOfficeGallerySerializer
|
||||
|
||||
def get_object(self):
|
||||
|
|
@ -218,7 +222,7 @@ class EstablishmentGalleryCreateDestroyView(EstablishmentMixinViews,
|
|||
"""
|
||||
establishment_qs = self.filter_queryset(self.get_queryset())
|
||||
|
||||
establishment = get_object_or_404(establishment_qs, pk=self.kwargs.get('pk'))
|
||||
establishment = get_object_or_404(establishment_qs, slug=self.kwargs.get('slug'))
|
||||
gallery = get_object_or_404(establishment.establishment_gallery,
|
||||
image_id=self.kwargs.get('image_id'))
|
||||
|
||||
|
|
@ -231,12 +235,13 @@ class EstablishmentGalleryCreateDestroyView(EstablishmentMixinViews,
|
|||
class EstablishmentGalleryListView(EstablishmentMixinViews,
|
||||
generics.ListAPIView):
|
||||
"""Resource for returning gallery for establishment for back-office users."""
|
||||
lookup_field = 'slug'
|
||||
serializer_class = serializers.ImageBaseSerializer
|
||||
|
||||
def get_object(self):
|
||||
"""Override get_object method."""
|
||||
qs = super(EstablishmentGalleryListView, self).get_queryset()
|
||||
establishment = get_object_or_404(qs, pk=self.kwargs.get('pk'))
|
||||
establishment = get_object_or_404(qs, slug=self.kwargs.get('slug'))
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, establishment)
|
||||
|
|
@ -252,6 +257,7 @@ class EstablishmentCompanyListCreateView(EstablishmentMixinViews,
|
|||
generics.ListCreateAPIView):
|
||||
"""List|Create establishment company view."""
|
||||
|
||||
lookup_field = 'slug'
|
||||
serializer_class = serializers.EstablishmentCompanyListCreateSerializer
|
||||
|
||||
def get_object(self):
|
||||
|
|
@ -259,7 +265,7 @@ class EstablishmentCompanyListCreateView(EstablishmentMixinViews,
|
|||
establishment_qs = models.Establishment.objects.all()
|
||||
filtered_ad_qs = self.filter_queryset(establishment_qs)
|
||||
|
||||
establishment = get_object_or_404(filtered_ad_qs, pk=self.kwargs.get('pk'))
|
||||
establishment = get_object_or_404(filtered_ad_qs, slug=self.kwargs.get('slug'))
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, establishment)
|
||||
|
|
@ -275,6 +281,7 @@ class EstablishmentCompanyRUDView(EstablishmentMixinViews,
|
|||
generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Create|Retrieve|Update|Destroy establishment company view."""
|
||||
|
||||
lookup_field = 'slug'
|
||||
serializer_class = serializers.CompanyBaseSerializer
|
||||
|
||||
def get_object(self):
|
||||
|
|
@ -282,7 +289,7 @@ class EstablishmentCompanyRUDView(EstablishmentMixinViews,
|
|||
establishment_qs = models.Establishment.objects.all()
|
||||
filtered_ad_qs = self.filter_queryset(establishment_qs)
|
||||
|
||||
establishment = get_object_or_404(filtered_ad_qs, pk=self.kwargs.get('pk'))
|
||||
establishment = get_object_or_404(filtered_ad_qs, slug=self.kwargs.get('slug'))
|
||||
company = get_object_or_404(establishment.companies.all(), pk=self.kwargs.get('company_pk'))
|
||||
|
||||
# May raise a permission denied
|
||||
|
|
@ -295,6 +302,7 @@ class EstablishmentNoteListCreateView(EstablishmentMixinViews,
|
|||
generics.ListCreateAPIView):
|
||||
"""Retrieve|Update|Destroy establishment note view."""
|
||||
|
||||
lookup_field = 'slug'
|
||||
serializer_class = serializers.EstablishmentNoteListCreateSerializer
|
||||
|
||||
def get_object(self):
|
||||
|
|
@ -302,7 +310,7 @@ class EstablishmentNoteListCreateView(EstablishmentMixinViews,
|
|||
establishment_qs = models.Establishment.objects.all()
|
||||
filtered_establishment_qs = self.filter_queryset(establishment_qs)
|
||||
|
||||
establishment = get_object_or_404(filtered_establishment_qs, pk=self.kwargs.get('pk'))
|
||||
establishment = get_object_or_404(filtered_establishment_qs, slug=self.kwargs.get('slug'))
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, establishment)
|
||||
|
|
@ -318,6 +326,7 @@ class EstablishmentNoteRUDView(EstablishmentMixinViews,
|
|||
generics.RetrieveUpdateDestroyAPIView):
|
||||
"""Create|Retrieve|Update|Destroy establishment note view."""
|
||||
|
||||
lookup_field = 'slug'
|
||||
serializer_class = serializers.EstablishmentNoteBaseSerializer
|
||||
|
||||
def get_object(self):
|
||||
|
|
@ -325,7 +334,7 @@ class EstablishmentNoteRUDView(EstablishmentMixinViews,
|
|||
establishment_qs = models.Establishment.objects.all()
|
||||
filtered_establishment_qs = self.filter_queryset(establishment_qs)
|
||||
|
||||
establishment = get_object_or_404(filtered_establishment_qs, pk=self.kwargs.get('pk'))
|
||||
establishment = get_object_or_404(filtered_establishment_qs, slug=self.kwargs.get('slug'))
|
||||
note = get_object_or_404(establishment.notes.all(), pk=self.kwargs['note_pk'])
|
||||
|
||||
# May raise a permission denied
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ class EstablishmentFavoritesCreateDestroyView(FavoritesCreateDestroyMixinView):
|
|||
class EstablishmentCarouselCreateDestroyView(CarouselCreateDestroyMixinView):
|
||||
"""View for create/destroy establishment from carousel."""
|
||||
|
||||
lookup_field = 'slug'
|
||||
_model = models.Establishment
|
||||
serializer_class = serializers.EstablishmentCarouselCreateSerializer
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ class Command(BaseCommand):
|
|||
new_address = Address.objects.filter(old_id=idx).first()
|
||||
if new_address:
|
||||
new_address.number = 0
|
||||
new_address.street_name_2 = ''
|
||||
new_address.street_name_1 = address
|
||||
update_address.append(new_address)
|
||||
|
||||
Address.objects.bulk_update(update_address, ['number', 'street_name_1'])
|
||||
Address.objects.bulk_update(update_address, ['number', 'street_name_1', 'street_name_2'])
|
||||
self.stdout.write(self.style.WARNING(f'Updated addresses: {len(update_address)}'))
|
||||
|
|
|
|||
17
apps/news/management/commands/rm_empty_images.py
Normal file
17
apps/news/management/commands/rm_empty_images.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
from django.core.management.base import BaseCommand
|
||||
|
||||
from news.models import News
|
||||
import re
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Removes empty img html tags from news description'
|
||||
|
||||
relative_img_regex = re.compile(r'\<img.+src=(?!https?:\/\/)([^\/].+?)[\"|\']>', re.I)
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
for news in News.objects.all():
|
||||
if isinstance(news.description, dict):
|
||||
news.description = {locale: self.relative_img_regex.sub('', rich_text)
|
||||
for locale, rich_text in news.description.items()}
|
||||
self.stdout.write(self.style.WARNING(f'Replaced {news} empty img html tags...\n'))
|
||||
news.save()
|
||||
|
|
@ -8,7 +8,7 @@ from partner.serializers import common as serializers
|
|||
# Mixins
|
||||
class PartnerViewMixin(generics.GenericAPIView):
|
||||
"""View mixin for Partner views"""
|
||||
queryset = models.Partner.objects.all()
|
||||
queryset = models.Partner.objects.distinct("name")
|
||||
|
||||
|
||||
# Views
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ class ProductFilterSet(filters.FilterSet):
|
|||
"""Product filter set."""
|
||||
|
||||
establishment_id = filters.NumberFilter()
|
||||
current_product = filters.CharFilter(method='without_current_product')
|
||||
product_type = filters.CharFilter(method='by_product_type')
|
||||
product_subtype = filters.CharFilter(method='by_product_subtype')
|
||||
|
||||
|
|
@ -21,6 +22,11 @@ class ProductFilterSet(filters.FilterSet):
|
|||
'product_subtype',
|
||||
]
|
||||
|
||||
def without_current_product(self, queryset, name, value):
|
||||
if value not in EMPTY_VALUES:
|
||||
return queryset.without_current_product(value)
|
||||
return queryset
|
||||
|
||||
def by_product_type(self, queryset, name, value):
|
||||
if value not in EMPTY_VALUES:
|
||||
return queryset.by_product_type(value)
|
||||
|
|
|
|||
|
|
@ -102,6 +102,11 @@ class ProductQuerySet(models.QuerySet):
|
|||
def wines(self):
|
||||
return self.filter(type__index_name__icontains=ProductType.WINE)
|
||||
|
||||
def without_current_product(self, current_product: str):
|
||||
"""Exclude by current product."""
|
||||
kwargs = {'pk': int(current_product)} if current_product.isdigit() else {'slug': current_product}
|
||||
return self.exclude(**kwargs)
|
||||
|
||||
def by_product_type(self, product_type: str):
|
||||
"""Filter by type."""
|
||||
return self.filter(product_type__index_name__icontains=product_type)
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ from rest_framework import serializers
|
|||
|
||||
from comment.models import Comment
|
||||
from comment.serializers import CommentSerializer
|
||||
from establishment.serializers import EstablishmentShortSerializer, EstablishmentProductSerializer, EstablishmentProductShortSerializer
|
||||
from gallery.models import Image
|
||||
from establishment.serializers import EstablishmentProductShortSerializer
|
||||
from establishment.serializers.common import _EstablishmentAddressShortSerializer
|
||||
from location.serializers import WineOriginRegionBaseSerializer, WineOriginBaseSerializer
|
||||
from main.serializers import AwardSerializer
|
||||
from product import models
|
||||
from review.serializers import ReviewShortSerializer
|
||||
from tag.serializers import TagBaseSerializer, TagCategoryProductSerializer
|
||||
from utils import exceptions as utils_exceptions
|
||||
from utils.serializers import TranslatedField, FavoritesCreateSerializer, ImageBaseSerializer
|
||||
from main.serializers import AwardSerializer
|
||||
from location.serializers import WineOriginRegionBaseSerializer, WineOriginBaseSerializer
|
||||
from tag.serializers import TagBaseSerializer, TagCategoryProductSerializer
|
||||
|
||||
|
||||
class ProductTagSerializer(TagBaseSerializer):
|
||||
|
|
@ -119,7 +119,7 @@ class ProductBaseSerializer(serializers.ModelSerializer):
|
|||
class ProductDetailSerializer(ProductBaseSerializer):
|
||||
"""Product detail serializer."""
|
||||
description_translated = TranslatedField()
|
||||
establishment_detail = EstablishmentShortSerializer(source='establishment', read_only=True)
|
||||
establishment_detail = _EstablishmentAddressShortSerializer(source='establishment', read_only=True)
|
||||
review = ReviewShortSerializer(source='last_published_review', read_only=True)
|
||||
awards = AwardSerializer(many=True, read_only=True)
|
||||
classifications = ProductClassificationBaseSerializer(many=True, read_only=True)
|
||||
|
|
|
|||
|
|
@ -45,8 +45,14 @@ class ScheduleRUDSerializer(serializers.ModelSerializer):
|
|||
.parser_context.get('view')\
|
||||
.kwargs.get('pk')
|
||||
|
||||
establishment_slug = self.context.get('request')\
|
||||
.parser_context.get('view')\
|
||||
.kwargs.get('slug')
|
||||
|
||||
search_kwargs = {'pk': establishment_pk} if establishment_pk else {'slug': establishment_slug}
|
||||
|
||||
# Check if establishment exists.
|
||||
establishment_qs = Establishment.objects.filter(pk=establishment_pk)
|
||||
establishment_qs = Establishment.objects.filter(**search_kwargs)
|
||||
if not establishment_qs.exists():
|
||||
raise serializers.ValidationError({'detail': _('Establishment not found.')})
|
||||
attrs['establishment'] = establishment_qs.first()
|
||||
|
|
|
|||
|
|
@ -118,6 +118,10 @@ class CarouselCreateSerializer(serializers.ModelSerializer):
|
|||
def pk(self):
|
||||
return self.request.parser_context.get('kwargs').get('pk')
|
||||
|
||||
@property
|
||||
def slug(self):
|
||||
return self.request.parser_context.get('kwargs').get('slug')
|
||||
|
||||
|
||||
class RecursiveFieldSerializer(serializers.Serializer):
|
||||
def to_representation(self, value):
|
||||
|
|
|
|||
|
|
@ -158,7 +158,11 @@ class CarouselCreateDestroyMixinView(BaseCreateDestroyMixinView):
|
|||
lookup_field = 'id'
|
||||
|
||||
def get_base_object(self):
|
||||
return get_object_or_404(self._model, id=self.kwargs['pk'])
|
||||
establishment_pk = self.kwargs.get('pk')
|
||||
establishment_slug = self.kwargs.get('slug')
|
||||
|
||||
search_kwargs = {'id': establishment_pk} if establishment_pk else {'slug': establishment_slug}
|
||||
return get_object_or_404(self._model, **search_kwargs)
|
||||
|
||||
def get_object(self):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ services:
|
|||
MYSQL_ROOT_PASSWORD: rootPassword
|
||||
volumes:
|
||||
- gm-mysql_db:/var/lib/mysql
|
||||
- .:/code
|
||||
|
||||
|
||||
|
||||
|
||||
# PostgreSQL database
|
||||
|
|
|
|||
|
|
@ -12,4 +12,5 @@
|
|||
./manage.py transfer --wine_characteristics
|
||||
./manage.py transfer --inquiries
|
||||
./manage.py transfer --assemblage
|
||||
./manage.py transfer --purchased_plaques
|
||||
./manage.py transfer --purchased_plaques
|
||||
./manage.py rm_empty_images
|
||||
|
|
@ -414,10 +414,10 @@ SORL_THUMBNAIL_ALIASES = {
|
|||
SIMPLE_JWT = {
|
||||
# Increase access token lifetime b.c. front-end dev's cant send multiple
|
||||
# requests to API in one HTTP request.
|
||||
'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
|
||||
'ACCESS_TOKEN_LIFETIME_SECONDS': 21600, # 6 hours in seconds
|
||||
'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
|
||||
'REFRESH_TOKEN_LIFETIME_SECONDS': 2592000, # 30 days in seconds
|
||||
'ACCESS_TOKEN_LIFETIME': timedelta(days=182),
|
||||
'ACCESS_TOKEN_LIFETIME_SECONDS': 15770000, # 6 months
|
||||
'REFRESH_TOKEN_LIFETIME': timedelta(days=182),
|
||||
'REFRESH_TOKEN_LIFETIME_SECONDS': 15770000, # 6 months
|
||||
'ROTATE_REFRESH_TOKENS': True,
|
||||
'BLACKLIST_AFTER_ROTATION': True,
|
||||
|
||||
|
|
@ -453,7 +453,7 @@ NOTIFICATION_PASSWORD_TEMPLATE = 'account/password_change_email.html'
|
|||
|
||||
|
||||
# COOKIES
|
||||
COOKIES_MAX_AGE = 2628000 # 30 days
|
||||
COOKIES_MAX_AGE = 15730000 # 6 months
|
||||
SESSION_COOKIE_SAMESITE = None
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ from django.urls import path, include
|
|||
app_name = 'mobile'
|
||||
|
||||
urlpatterns = [
|
||||
path('booking/', include('booking.urls.web')),
|
||||
path('establishments/', include('establishment.urls.mobile')),
|
||||
path('location/', include('location.urls.mobile')),
|
||||
path('main/', include('main.urls.mobile')),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ app_name = 'web'
|
|||
|
||||
urlpatterns = [
|
||||
path('account/', include('account.urls.web')),
|
||||
path('booking/', include('booking.urls')),
|
||||
path('booking/', include('booking.urls.web')),
|
||||
path('re_blocks/', include('advertisement.urls.web')),
|
||||
path('collections/', include('collection.urls.web')),
|
||||
path('establishments/', include('establishment.urls.web')),
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user