GM-127: in progress
This commit is contained in:
parent
8766388256
commit
207e35feb1
|
|
@ -1,18 +1,20 @@
|
||||||
"""Establishment models."""
|
"""Establishment models."""
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from django.contrib.gis.db.models.functions import Distance
|
|
||||||
|
|
||||||
from django.contrib.gis.measure import Distance as DistanceMeasure
|
from django.conf import settings
|
||||||
from django.contrib.gis.geos import Point
|
|
||||||
from django.contrib.contenttypes import fields as generic
|
from django.contrib.contenttypes import fields as generic
|
||||||
|
from django.contrib.gis.db.models.functions import Distance
|
||||||
|
from django.contrib.gis.geos import Point
|
||||||
|
from django.contrib.gis.measure import Distance as DistanceMeasure
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import When, Case, F, ExpressionWrapper, Subquery
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from phonenumber_field.modelfields import PhoneNumberField
|
from phonenumber_field.modelfields import PhoneNumberField
|
||||||
|
|
||||||
from location.models import Address
|
|
||||||
from collection.models import Collection
|
from collection.models import Collection
|
||||||
|
from location.models import Address
|
||||||
from review.models import Review
|
from review.models import Review
|
||||||
from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField, URLImageMixin,
|
from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField, URLImageMixin,
|
||||||
TranslatedFieldsMixin, BaseAttributes)
|
TranslatedFieldsMixin, BaseAttributes)
|
||||||
|
|
@ -128,27 +130,28 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
output_field=models.FloatField()
|
output_field=models.FloatField()
|
||||||
))
|
))
|
||||||
|
|
||||||
def similar(self, establishment_slug: str, output_objects: int = 12):
|
def similar(self, establishment_slug: str):
|
||||||
"""
|
"""
|
||||||
Return QuerySet with objects that similar to Establishment.
|
Return QuerySet with objects that similar to Establishment.
|
||||||
:param establishment_slug: str Establishment slug
|
:param establishment_slug: str Establishment slug
|
||||||
:param output_objects: int of output objects
|
|
||||||
"""
|
"""
|
||||||
establishment_qs = Establishment.objects.filter(slug=establishment_slug,
|
establishment_qs = Establishment.objects.filter(slug=establishment_slug,
|
||||||
public_mark__isnull=False)
|
public_mark__isnull=False)
|
||||||
if establishment_qs.exists():
|
if establishment_qs.exists():
|
||||||
establishment = establishment_qs.first()
|
establishment = establishment_qs.first()
|
||||||
return self.exclude(slug=establishment_slug) \
|
subquery_filter_by_distance = Subquery(
|
||||||
.filter(is_publish=True,
|
self.exclude(slug=establishment_slug)
|
||||||
image_url__isnull=False,
|
.filter(image_url__isnull=False, public_mark__gte=10)
|
||||||
reviews__isnull=False,
|
.published()
|
||||||
reviews__status=Review.READY,
|
.has_published_reviews()
|
||||||
public_mark__gte=10) \
|
.annotate_distance(point=establishment.address.coordinates)
|
||||||
.annotate_distance(point=establishment.address.coordinates) \
|
.order_by('distance')[:settings.LIMITING_QUERY_NUMBER]
|
||||||
|
.values('id')
|
||||||
|
)
|
||||||
|
return Establishment.objects.filter(id__in=subquery_filter_by_distance) \
|
||||||
.annotate_intermediate_public_mark() \
|
.annotate_intermediate_public_mark() \
|
||||||
.annotate_mark_similarity(mark=establishment.public_mark) \
|
.annotate_mark_similarity(mark=establishment.public_mark) \
|
||||||
.order_by('distance') \
|
.order_by('mark_similarity')
|
||||||
.order_by('mark_similarity')[:output_objects]
|
|
||||||
else:
|
else:
|
||||||
return self.none()
|
return self.none()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ class EstablishmentDetailSerializer(EstablishmentListSerializer):
|
||||||
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
||||||
phones = ContactPhonesSerializer(read_only=True, many=True, )
|
phones = ContactPhonesSerializer(read_only=True, many=True, )
|
||||||
emails = ContactEmailsSerializer(read_only=True, many=True, )
|
emails = ContactEmailsSerializer(read_only=True, many=True, )
|
||||||
review = serializers.SerializerMethodField()
|
review = ReviewSerializer(source='last_published_review', allow_null=True)
|
||||||
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
||||||
many=True)
|
many=True)
|
||||||
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
||||||
|
|
@ -201,7 +201,7 @@ class EstablishmentDetailSerializer(EstablishmentListSerializer):
|
||||||
|
|
||||||
slug = serializers.SlugField(required=True, allow_blank=False, max_length=50)
|
slug = serializers.SlugField(required=True, allow_blank=False, max_length=50)
|
||||||
|
|
||||||
in_favorites = serializers.SerializerMethodField()
|
in_favorites = serializers.BooleanField()
|
||||||
|
|
||||||
image = serializers.URLField(source='image_url')
|
image = serializers.URLField(source='image_url')
|
||||||
|
|
||||||
|
|
@ -231,21 +231,6 @@ class EstablishmentDetailSerializer(EstablishmentListSerializer):
|
||||||
'slug',
|
'slug',
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_review(self, obj):
|
|
||||||
"""Serializer method for getting last published review"""
|
|
||||||
return ReviewSerializer(obj.reviews.by_status(status=review_models.Review.READY)
|
|
||||||
.order_by('-published_at').first()).data
|
|
||||||
|
|
||||||
def get_in_favorites(self, obj):
|
|
||||||
"""Get in_favorites status flag"""
|
|
||||||
user = self.context.get('request').user
|
|
||||||
if user.is_authenticated:
|
|
||||||
return obj.id in user.favorites.by_content_type(app_label='establishment',
|
|
||||||
model='establishment')\
|
|
||||||
.values_list('object_id', flat=True)
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentCommentCreateSerializer(comment_serializers.CommentSerializer):
|
class EstablishmentCommentCreateSerializer(comment_serializers.CommentSerializer):
|
||||||
"""Create comment serializer"""
|
"""Create comment serializer"""
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ from establishment import filters
|
||||||
from establishment import models, serializers
|
from establishment import models, serializers
|
||||||
from establishment.views import EstablishmentMixin
|
from establishment.views import EstablishmentMixin
|
||||||
from main.models import MetaDataContent
|
from main.models import MetaDataContent
|
||||||
|
from utils.pagination import EstablishmentPagination
|
||||||
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
|
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -27,10 +28,12 @@ class EstablishmentListView(EstablishmentMixin, generics.ListAPIView):
|
||||||
class EstablishmentSimilarListView(EstablishmentListView):
|
class EstablishmentSimilarListView(EstablishmentListView):
|
||||||
"""Resource for getting a list of establishments."""
|
"""Resource for getting a list of establishments."""
|
||||||
serializer_class = serializers.EstablishmentListSerializer
|
serializer_class = serializers.EstablishmentListSerializer
|
||||||
|
pagination_class = EstablishmentPagination
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Override get_queryset method"""
|
"""Override get_queryset method"""
|
||||||
return super().get_queryset().similar(establishment_slug=self.kwargs.get('slug'))
|
return super().get_queryset() \
|
||||||
|
.similar(establishment_slug=self.kwargs.get('slug'))
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentRetrieveView(EstablishmentMixin, generics.RetrieveAPIView):
|
class EstablishmentRetrieveView(EstablishmentMixin, generics.RetrieveAPIView):
|
||||||
|
|
@ -38,6 +41,11 @@ class EstablishmentRetrieveView(EstablishmentMixin, generics.RetrieveAPIView):
|
||||||
lookup_field = 'slug'
|
lookup_field = 'slug'
|
||||||
serializer_class = serializers.EstablishmentDetailSerializer
|
serializer_class = serializers.EstablishmentDetailSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""Override 'get_queryset' method."""
|
||||||
|
return super(EstablishmentRetrieveView, self).get_queryset() \
|
||||||
|
.annotate_in_favorites(self.request.user)
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentTypeListView(generics.ListAPIView):
|
class EstablishmentTypeListView(generics.ListAPIView):
|
||||||
"""Resource for getting a list of establishment types."""
|
"""Resource for getting a list of establishment types."""
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@ class ReviewQuerySet(models.QuerySet):
|
||||||
"""Filter by status"""
|
"""Filter by status"""
|
||||||
return self.filter(status=status)
|
return self.filter(status=status)
|
||||||
|
|
||||||
|
def published(self):
|
||||||
|
"""Return published reviews"""
|
||||||
|
return self.filter(status=Review.READY)
|
||||||
|
|
||||||
|
|
||||||
class Review(BaseAttributes, TranslatedFieldsMixin):
|
class Review(BaseAttributes, TranslatedFieldsMixin):
|
||||||
"""Review model"""
|
"""Review model"""
|
||||||
|
|
|
||||||
|
|
@ -44,3 +44,10 @@ class ProjectMobilePagination(ProjectPageNumberPagination):
|
||||||
if not self.page.has_previous():
|
if not self.page.has_previous():
|
||||||
return None
|
return None
|
||||||
return self.page.previous_page_number()
|
return self.page.previous_page_number()
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentPagination(ProjectMobilePagination):
|
||||||
|
"""
|
||||||
|
Pagination for app establishments with limit page size equal to 12
|
||||||
|
"""
|
||||||
|
page_size = 12
|
||||||
|
|
|
||||||
|
|
@ -412,3 +412,5 @@ SOLO_CACHE_TIMEOUT = 300
|
||||||
SITE_REDIRECT_URL_UNSUBSCRIBE = '/unsubscribe/'
|
SITE_REDIRECT_URL_UNSUBSCRIBE = '/unsubscribe/'
|
||||||
|
|
||||||
SITE_NAME = 'Gault & Millau'
|
SITE_NAME = 'Gault & Millau'
|
||||||
|
|
||||||
|
LIMITING_QUERY_NUMBER = 36 # Need to restrict objects to sort (used in establishments)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user