Merge branch 'develop' into feature/permission_winery

This commit is contained in:
Виктор Гладких 2019-12-06 16:58:44 +03:00
commit 8e63b969bf
25 changed files with 159 additions and 49 deletions

View File

View 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
View File

@ -0,0 +1,8 @@
from booking.urls import common as common_views
app = 'booking'
urlpatterns_api = []
urlpatterns = urlpatterns_api + \
common_views.urlpatterns

View File

@ -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:

View File

@ -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():

View File

@ -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.')})

View File

@ -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)

View File

@ -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'),

View File

@ -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

View File

@ -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

View File

@ -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)}'))

View 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()

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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):

View File

@ -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):
"""

View File

@ -13,6 +13,9 @@ services:
MYSQL_ROOT_PASSWORD: rootPassword
volumes:
- gm-mysql_db:/var/lib/mysql
- .:/code
# PostgreSQL database

View File

@ -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

View File

@ -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

View File

@ -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')),

View File

@ -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')),