intermediate commit
This commit is contained in:
parent
f87d891daa
commit
7452f0bef0
|
|
@ -568,6 +568,10 @@ class GuideElementQuerySet(models.QuerySet):
|
||||||
"""Return GuideElement with type WineNode."""
|
"""Return GuideElement with type WineNode."""
|
||||||
return self.filter(guide_element_type__name='WineNode')
|
return self.filter(guide_element_type__name='WineNode')
|
||||||
|
|
||||||
|
def descendants(self):
|
||||||
|
"""Return QuerySet with descendants."""
|
||||||
|
return self.exclude(guide_element_type__name='Root')
|
||||||
|
|
||||||
|
|
||||||
class GuideElement(ProjectBaseMixin, MPTTModel):
|
class GuideElement(ProjectBaseMixin, MPTTModel):
|
||||||
"""Frozen state of elements of guide instance."""
|
"""Frozen state of elements of guide instance."""
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ from collection import models
|
||||||
from location import models as location_models
|
from location import models as location_models
|
||||||
from main.serializers import SiteShortSerializer
|
from main.serializers import SiteShortSerializer
|
||||||
from utils.serializers import TranslatedField
|
from utils.serializers import TranslatedField
|
||||||
|
from rest_framework_recursive.fields import RecursiveField
|
||||||
|
from establishment.serializers import EstablishmentGuideElementSerializer
|
||||||
|
from product.serializers import ProductGuideElementSerializer
|
||||||
|
|
||||||
|
|
||||||
class CollectionBaseSerializer(serializers.ModelSerializer):
|
class CollectionBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -94,7 +97,8 @@ class GuideBaseSerializer(serializers.ModelSerializer):
|
||||||
restaurant_counter = serializers.IntegerField(read_only=True)
|
restaurant_counter = serializers.IntegerField(read_only=True)
|
||||||
shop_counter = serializers.IntegerField(read_only=True)
|
shop_counter = serializers.IntegerField(read_only=True)
|
||||||
wine_counter = serializers.IntegerField(read_only=True)
|
wine_counter = serializers.IntegerField(read_only=True)
|
||||||
present_objects_counter = serializers.IntegerField(read_only=True)
|
count_objects_during_init = serializers.IntegerField(read_only=True,
|
||||||
|
source='count_related_objects')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Guide
|
model = models.Guide
|
||||||
|
|
@ -115,7 +119,6 @@ class GuideBaseSerializer(serializers.ModelSerializer):
|
||||||
'restaurant_counter',
|
'restaurant_counter',
|
||||||
'shop_counter',
|
'shop_counter',
|
||||||
'wine_counter',
|
'wine_counter',
|
||||||
'present_objects_counter',
|
|
||||||
'count_objects_during_init',
|
'count_objects_during_init',
|
||||||
]
|
]
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
|
|
@ -166,3 +169,36 @@ class GuideFilterBaseSerializer(serializers.ModelSerializer):
|
||||||
"""Overridden create method."""
|
"""Overridden create method."""
|
||||||
validated_data['guide'] = self.get_guide(validated_data.pop('guide', None))
|
validated_data['guide'] = self.get_guide(validated_data.pop('guide', None))
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
|
||||||
|
class GuideElementBaseSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serializer for model GuideElement."""
|
||||||
|
establishment_detail = EstablishmentGuideElementSerializer(read_only=True,
|
||||||
|
source='establishment')
|
||||||
|
section_name = serializers.CharField(source='section.name',
|
||||||
|
allow_null=True)
|
||||||
|
wine_color_section_name = serializers.CharField(source='wine_color_section.name',
|
||||||
|
allow_null=True)
|
||||||
|
node_name = serializers.CharField(source='guide_element_type.name')
|
||||||
|
label_photo = serializers.ImageField(source='label_photo.image', allow_null=True)
|
||||||
|
city_name = serializers.CharField(source='city.name', allow_null=True)
|
||||||
|
product_detail = ProductGuideElementSerializer(read_only=True, source='product')
|
||||||
|
|
||||||
|
parent = RecursiveField(required=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
model = models.GuideElement
|
||||||
|
fields = [
|
||||||
|
'node_name',
|
||||||
|
'establishment_detail',
|
||||||
|
'review',
|
||||||
|
'wine_region',
|
||||||
|
'product_detail',
|
||||||
|
'priority',
|
||||||
|
'city_name',
|
||||||
|
'section_name',
|
||||||
|
'wine_color_section_name',
|
||||||
|
'parent',
|
||||||
|
'label_photo',
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ router.register(r'collections', views.CollectionBackOfficeViewSet)
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('guides/', views.GuideListCreateView.as_view(),
|
path('guides/', views.GuideListCreateView.as_view(),
|
||||||
name='guide-list-create'),
|
name='guide-list-create'),
|
||||||
# path('guides/<int:pk>/elements/', views.GuideElementListView.as_view(),
|
path('guides/<int:pk>/', views.GuideElementListView.as_view(),
|
||||||
# name='guide-element-list'),
|
name='guide-element-list'),
|
||||||
path('guides/<int:pk>/filters/', views.GuideFilterCreateView.as_view(),
|
path('guides/<int:pk>/filters/', views.GuideFilterCreateView.as_view(),
|
||||||
name='guide-filter-list-create'),
|
name='guide-filter-list-create'),
|
||||||
] + router.urls
|
] + router.urls
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from rest_framework import mixins, permissions, viewsets
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.filters import OrderingFilter
|
from rest_framework.filters import OrderingFilter
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
from collection import models, serializers
|
from collection import models, serializers
|
||||||
from utils.views import BindObjectMixin
|
from utils.views import BindObjectMixin
|
||||||
|
|
@ -27,7 +28,7 @@ class CollectionViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
|
||||||
class GuideBaseView(generics.GenericAPIView):
|
class GuideBaseView(generics.GenericAPIView):
|
||||||
"""ViewSet for Guide model."""
|
"""ViewSet for Guide model."""
|
||||||
serializer_class = serializers.GuideBaseSerializer
|
serializer_class = serializers.GuideBaseSerializer
|
||||||
permission_classes = (permissions.IsAuthenticated, )
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Overridden get_queryset method."""
|
"""Overridden get_queryset method."""
|
||||||
|
|
@ -43,7 +44,15 @@ class GuideFilterBaseView(generics.GenericAPIView):
|
||||||
pagination_class = None
|
pagination_class = None
|
||||||
queryset = models.GuideFilter.objects.all()
|
queryset = models.GuideFilter.objects.all()
|
||||||
serializer_class = serializers.GuideFilterBaseSerializer
|
serializer_class = serializers.GuideFilterBaseSerializer
|
||||||
permission_classes = (permissions.IsAuthenticated,)
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
|
||||||
|
|
||||||
|
class GuideElementBaseView(generics.GenericAPIView):
|
||||||
|
"""Base view for GuideElement model."""
|
||||||
|
pagination_class = None
|
||||||
|
queryset = models.GuideElement.objects.all()
|
||||||
|
serializer_class = serializers.GuideElementBaseSerializer
|
||||||
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
|
||||||
|
|
||||||
class CollectionBackOfficeViewSet(mixins.CreateModelMixin,
|
class CollectionBackOfficeViewSet(mixins.CreateModelMixin,
|
||||||
|
|
@ -98,3 +107,14 @@ class GuideFilterCreateView(GuideFilterBaseView,
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
super().create(request, *args, **kwargs)
|
super().create(request, *args, **kwargs)
|
||||||
return Response(status=status.HTTP_200_OK)
|
return Response(status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
|
class GuideElementListView(GuideElementBaseView,
|
||||||
|
generics.ListAPIView):
|
||||||
|
"""View for model GuideElement for back office users."""
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""Overridden get_queryset method."""
|
||||||
|
guide = get_object_or_404(models.Guide.objects.all(), pk=self.kwargs.get('pk'))
|
||||||
|
return models.GuideElement.objects.get_root_node(guide) \
|
||||||
|
.get_descendants()
|
||||||
|
|
|
||||||
|
|
@ -244,8 +244,9 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
return Subquery(
|
return Subquery(
|
||||||
self.similar_base(establishment)
|
self.similar_base(establishment)
|
||||||
.filter(**filters)
|
.filter(**filters)
|
||||||
.order_by('distance')[:settings.LIMITING_QUERY_OBJECTS]
|
.order_by('distance')
|
||||||
.values('id')
|
.distinct()
|
||||||
|
.values_list('id', flat=True)[:settings.LIMITING_QUERY_OBJECTS]
|
||||||
)
|
)
|
||||||
|
|
||||||
def similar_restaurants(self, slug):
|
def similar_restaurants(self, slug):
|
||||||
|
|
@ -263,7 +264,8 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
'establishment_gallery__is_main': True,
|
'establishment_gallery__is_main': True,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return self.filter(id__in=ids_by_subquery) \
|
# todo: fix this - replace ids_by_subquery.queryset on ids_by_subquery
|
||||||
|
return self.filter(id__in=ids_by_subquery.queryset) \
|
||||||
.annotate_intermediate_public_mark() \
|
.annotate_intermediate_public_mark() \
|
||||||
.annotate_mark_similarity(mark=restaurant.public_mark) \
|
.annotate_mark_similarity(mark=restaurant.public_mark) \
|
||||||
.order_by('mark_similarity') \
|
.order_by('mark_similarity') \
|
||||||
|
|
|
||||||
|
|
@ -621,3 +621,33 @@ class CompanyBaseSerializer(serializers.ModelSerializer):
|
||||||
if models.Company.objects.filter(phones__overlap=phones).exists():
|
if models.Company.objects.filter(phones__overlap=phones).exists():
|
||||||
raise serializers.ValidationError({'detail': _('Phones is already reserved.')})
|
raise serializers.ValidationError({'detail': _('Phones is already reserved.')})
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentGuideElementSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serializer for Guide serializer."""
|
||||||
|
type = EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True)
|
||||||
|
subtypes = EstablishmentSubTypeBaseSerializer(many=True, source='establishment_subtypes')
|
||||||
|
address = AddressBaseSerializer()
|
||||||
|
tz = serializers.CharField(read_only=True, source='timezone_as_str')
|
||||||
|
schedule = ScheduleRUDSerializer(many=True, allow_null=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)
|
||||||
|
range_price_menu = RangePriceSerializer(read_only=True)
|
||||||
|
range_price_carte = RangePriceSerializer(read_only=True)
|
||||||
|
currency = CurrencySerializer()
|
||||||
|
|
||||||
|
class Meta(EstablishmentBaseSerializer.Meta):
|
||||||
|
"""Meta class."""
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'type',
|
||||||
|
'subtypes',
|
||||||
|
'address',
|
||||||
|
'tz',
|
||||||
|
'schedule',
|
||||||
|
'best_price_menu',
|
||||||
|
'best_price_carte',
|
||||||
|
'range_price_menu',
|
||||||
|
'range_price_carte',
|
||||||
|
'currency',
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView):
|
||||||
class EstablishmentSimilarView(EstablishmentListView):
|
class EstablishmentSimilarView(EstablishmentListView):
|
||||||
"""Resource for getting a list of similar establishments."""
|
"""Resource for getting a list of similar establishments."""
|
||||||
serializer_class = serializers.EstablishmentSimilarSerializer
|
serializer_class = serializers.EstablishmentSimilarSerializer
|
||||||
pagination_class = PortionPagination
|
pagination_class = None
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
||||||
|
|
@ -90,7 +90,7 @@ class RestaurantSimilarListView(EstablishmentSimilarView):
|
||||||
"""Overridden get_queryset method"""
|
"""Overridden get_queryset method"""
|
||||||
return EstablishmentMixinView.get_queryset(self) \
|
return EstablishmentMixinView.get_queryset(self) \
|
||||||
.has_location() \
|
.has_location() \
|
||||||
.similar_restaurants(slug=self.kwargs.get('slug'))
|
.similar_restaurants(slug=self.kwargs.get('slug'))[:settings.QUERY_OUTPUT_OBJECTS]
|
||||||
|
|
||||||
|
|
||||||
class WinerySimilarListView(EstablishmentSimilarView):
|
class WinerySimilarListView(EstablishmentSimilarView):
|
||||||
|
|
@ -100,7 +100,7 @@ class WinerySimilarListView(EstablishmentSimilarView):
|
||||||
"""Overridden get_queryset method"""
|
"""Overridden get_queryset method"""
|
||||||
return EstablishmentMixinView.get_queryset(self) \
|
return EstablishmentMixinView.get_queryset(self) \
|
||||||
.has_location() \
|
.has_location() \
|
||||||
.similar_wineries(slug=self.kwargs.get('slug'))
|
.similar_wineries(slug=self.kwargs.get('slug'))[:settings.QUERY_OUTPUT_OBJECTS]
|
||||||
|
|
||||||
|
|
||||||
class ArtisanProducerSimilarListView(EstablishmentSimilarView):
|
class ArtisanProducerSimilarListView(EstablishmentSimilarView):
|
||||||
|
|
@ -110,7 +110,7 @@ class ArtisanProducerSimilarListView(EstablishmentSimilarView):
|
||||||
"""Overridden get_queryset method"""
|
"""Overridden get_queryset method"""
|
||||||
return EstablishmentMixinView.get_queryset(self) \
|
return EstablishmentMixinView.get_queryset(self) \
|
||||||
.has_location() \
|
.has_location() \
|
||||||
.similar_artisans_producers(slug=self.kwargs.get('slug'))
|
.similar_artisans_producers(slug=self.kwargs.get('slug'))[:settings.QUERY_OUTPUT_OBJECTS]
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentTypeListView(generics.ListAPIView):
|
class EstablishmentTypeListView(generics.ListAPIView):
|
||||||
|
|
|
||||||
|
|
@ -219,3 +219,15 @@ class ProductCommentCreateSerializer(CommentSerializer):
|
||||||
'content_object': validated_data.pop('product')
|
'content_object': validated_data.pop('product')
|
||||||
})
|
})
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
|
||||||
|
class ProductGuideElementSerializer(ProductBaseSerializer):
|
||||||
|
"""Serializer for serializing in GuideElement for model Product."""
|
||||||
|
|
||||||
|
class Meta(ProductBaseSerializer.Meta):
|
||||||
|
"""Meta class."""
|
||||||
|
_unused_fields = ('tags', 'wine_regions', 'wine_colors', 'preview_image_url')
|
||||||
|
fields = ProductBaseSerializer.Meta.fields
|
||||||
|
|
||||||
|
# pop unused fields
|
||||||
|
for unused_field in _unused_fields: fields.pop(fields.index(unused_field))
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ from product import filters, serializers
|
||||||
from comment.serializers import CommentRUDSerializer
|
from comment.serializers import CommentRUDSerializer
|
||||||
from utils.views import FavoritesCreateDestroyMixinView
|
from utils.views import FavoritesCreateDestroyMixinView
|
||||||
from utils.pagination import PortionPagination
|
from utils.pagination import PortionPagination
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
class ProductBaseView(generics.GenericAPIView):
|
class ProductBaseView(generics.GenericAPIView):
|
||||||
|
|
@ -97,5 +98,5 @@ class SimilarListView(ProductSimilarView):
|
||||||
"""Overridden get_queryset method."""
|
"""Overridden get_queryset method."""
|
||||||
return super().get_queryset() \
|
return super().get_queryset() \
|
||||||
.has_location() \
|
.has_location() \
|
||||||
.similar(slug=self.kwargs.get('slug'))
|
.similar(slug=self.kwargs.get('slug'))[:settings.QUERY_OUTPUT_OBJECTS]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class TimeZoneChoiceField(serializers.ChoiceField):
|
||||||
|
|
||||||
|
|
||||||
class ProjectModelSerializer(serializers.ModelSerializer):
|
class ProjectModelSerializer(serializers.ModelSerializer):
|
||||||
"""Overrided ModelSerializer."""
|
"""Overridden ModelSerializer."""
|
||||||
|
|
||||||
serializers.ModelSerializer.serializer_field_mapping[models.TJSONField] = TJSONField
|
serializers.ModelSerializer.serializer_field_mapping[models.TJSONField] = TJSONField
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,3 +63,6 @@ pycountry==19.8.18
|
||||||
|
|
||||||
# sql-tree
|
# sql-tree
|
||||||
django-mptt==0.9.1
|
django-mptt==0.9.1
|
||||||
|
|
||||||
|
# For recursive fields
|
||||||
|
djangorestframework-recursive==0.1.2
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user