gm-127: finished
This commit is contained in:
parent
0e0d6e318e
commit
c4d8b89a8d
|
|
@ -93,15 +93,20 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
"""
|
"""
|
||||||
return self.filter(is_publish=True)
|
return self.filter(is_publish=True)
|
||||||
|
|
||||||
def annotate_distance(self, point: Point):
|
def has_published_reviews(self):
|
||||||
|
"""
|
||||||
|
Return QuerySet establishments with published reviews.
|
||||||
|
"""
|
||||||
|
return self.filter(reviews__status=Review.READY,)
|
||||||
|
|
||||||
|
def annotate_distance(self, point: Point = None):
|
||||||
"""
|
"""
|
||||||
Return QuerySet with annotated field - distance
|
Return QuerySet with annotated field - distance
|
||||||
Description:
|
Description:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return self.annotate(distance=models.Value(
|
return self.annotate(distance=Distance('address__coordinates', point,
|
||||||
DistanceMeasure(Distance('address__coordinates', point, srid=4236)).m,
|
srid=settings.GEO_DEFAULT_SRID))
|
||||||
output_field=models.FloatField()))
|
|
||||||
|
|
||||||
def annotate_intermediate_public_mark(self):
|
def annotate_intermediate_public_mark(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -110,8 +115,8 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
If establishments in collection POP and its mark is null, then
|
If establishments in collection POP and its mark is null, then
|
||||||
intermediate_mark is set to 10;
|
intermediate_mark is set to 10;
|
||||||
"""
|
"""
|
||||||
return self.annotate(intermediate_public_mark=models.Case(
|
return self.annotate(intermediate_public_mark=Case(
|
||||||
models.When(
|
When(
|
||||||
collections__collection_type=Collection.POP,
|
collections__collection_type=Collection.POP,
|
||||||
public_mark__isnull=True,
|
public_mark__isnull=True,
|
||||||
then=settings.DEFAULT_ESTABLISHMENT_PUBLIC_MARK
|
then=settings.DEFAULT_ESTABLISHMENT_PUBLIC_MARK
|
||||||
|
|
@ -125,8 +130,8 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
Description:
|
Description:
|
||||||
Similarity mark determined by comparison with compared establishment mark
|
Similarity mark determined by comparison with compared establishment mark
|
||||||
"""
|
"""
|
||||||
return self.annotate(mark_similarity=models.ExpressionWrapper(
|
return self.annotate(mark_similarity=ExpressionWrapper(
|
||||||
mark - models.F('intermediate_public_mark'),
|
mark - F('intermediate_public_mark'),
|
||||||
output_field=models.FloatField()
|
output_field=models.FloatField()
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
@ -154,6 +159,21 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
else:
|
else:
|
||||||
return self.none()
|
return self.none()
|
||||||
|
|
||||||
|
def last_reviewed(self, point: Point):
|
||||||
|
"""
|
||||||
|
Return QuerySet with last reviewed establishments.
|
||||||
|
:param point: location Point object, needs to ordering
|
||||||
|
"""
|
||||||
|
subquery_filter_by_distance = Subquery(
|
||||||
|
self.filter(image_url__isnull=False, public_mark__gte=10)
|
||||||
|
.has_published_reviews()
|
||||||
|
.annotate_distance(point=point)
|
||||||
|
.order_by('distance')[:settings.LIMITING_QUERY_NUMBER]
|
||||||
|
.values('id')
|
||||||
|
)
|
||||||
|
return self.filter(id__in=subquery_filter_by_distance) \
|
||||||
|
.order_by('-reviews__published_at')
|
||||||
|
|
||||||
def prefetch_actual_employees(self):
|
def prefetch_actual_employees(self):
|
||||||
"""Prefetch actual employees."""
|
"""Prefetch actual employees."""
|
||||||
return self.prefetch_related(
|
return self.prefetch_related(
|
||||||
|
|
@ -169,8 +189,8 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
favorite_establishments = user.favorites.by_content_type(app_label='establishment',
|
favorite_establishments = user.favorites.by_content_type(app_label='establishment',
|
||||||
model='establishment') \
|
model='establishment') \
|
||||||
.values_list('object_id', flat=True)
|
.values_list('object_id', flat=True)
|
||||||
return self.annotate(in_favorites=models.Case(
|
return self.annotate(in_favorites=Case(
|
||||||
models.When(
|
When(
|
||||||
id__in=favorite_establishments,
|
id__in=favorite_establishments,
|
||||||
then=True),
|
then=True),
|
||||||
default=False,
|
default=False,
|
||||||
|
|
@ -194,7 +214,7 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
||||||
|
|
||||||
name = models.CharField(_('name'), max_length=255, default='')
|
name = models.CharField(_('name'), max_length=255, default='')
|
||||||
name_translated = models.CharField(_('Transliterated name'),
|
name_translated = models.CharField(_('Transliterated name'),
|
||||||
max_length=255, default='')
|
max_length=255, default='')
|
||||||
description = TJSONField(blank=True, null=True, default=None,
|
description = TJSONField(blank=True, null=True, default=None,
|
||||||
verbose_name=_('description'),
|
verbose_name=_('description'),
|
||||||
help_text='{"en-GB":"some text"}')
|
help_text='{"en-GB":"some text"}')
|
||||||
|
|
@ -308,6 +328,19 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
||||||
return [{'id': tag.metadata.id,
|
return [{'id': tag.metadata.id,
|
||||||
'label': tag.metadata.label} for tag in self.tags.all()]
|
'label': tag.metadata.label} for tag in self.tags.all()]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def last_published_review(self):
|
||||||
|
"""Return last published review"""
|
||||||
|
return self.reviews.published()\
|
||||||
|
.order_by('-published_at').first()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def location(self):
|
||||||
|
"""
|
||||||
|
Return Point object of establishment location
|
||||||
|
"""
|
||||||
|
return self.address.coordinates
|
||||||
|
|
||||||
|
|
||||||
class Position(BaseAttributes, TranslatedFieldsMixin):
|
class Position(BaseAttributes, TranslatedFieldsMixin):
|
||||||
"""Position model."""
|
"""Position model."""
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ app_name = 'establishment'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', views.EstablishmentListView.as_view(), name='list'),
|
path('', views.EstablishmentListView.as_view(), name='list'),
|
||||||
path('tags/', views.EstablishmentTagListView.as_view(), name='tags'),
|
path('tags/', views.EstablishmentTagListView.as_view(), name='tags'),
|
||||||
|
path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(),
|
||||||
|
name='recent-reviews'),
|
||||||
path('<slug:slug>/', views.EstablishmentRetrieveView.as_view(), name='detail'),
|
path('<slug:slug>/', views.EstablishmentRetrieveView.as_view(), name='detail'),
|
||||||
path('<slug:slug>/similar/', views.EstablishmentSimilarListView.as_view(), name='similar'),
|
path('<slug:slug>/similar/', views.EstablishmentSimilarListView.as_view(), name='similar'),
|
||||||
path('<slug:slug>/comments/', views.EstablishmentCommentListView.as_view(), name='list-comments'),
|
path('<slug:slug>/comments/', views.EstablishmentCommentListView.as_view(), name='list-comments'),
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,6 @@ class EstablishmentMixin:
|
||||||
permission_classes = (permissions.AllowAny,)
|
permission_classes = (permissions.AllowAny,)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
"""Overrided method 'get_queryset'."""
|
"""Overridden method 'get_queryset'."""
|
||||||
return models.Establishment.objects.published() \
|
return models.Establishment.objects.published() \
|
||||||
.prefetch_actual_employees()
|
.prefetch_actual_employees()
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,25 @@ class EstablishmentListView(EstablishmentMixin, generics.ListAPIView):
|
||||||
.annotate_in_favorites(user=self.request.user)
|
.annotate_in_favorites(user=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentRecentReviewListView(EstablishmentListView):
|
||||||
|
"""List view for last reviewed establishments."""
|
||||||
|
pagination_class = EstablishmentPortionPagination
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""Overridden method 'get_queryset'."""
|
||||||
|
qs = super().get_queryset()
|
||||||
|
user_ip = methods.get_user_ip(self.request)
|
||||||
|
query_params = self.request.query_params
|
||||||
|
if 'longitude' in query_params and 'latitude' in query_params:
|
||||||
|
longitude, latitude = query_params.get('longitude'), query_params.get('latitude')
|
||||||
|
else:
|
||||||
|
longitude, latitude = methods.determine_coordinates(user_ip)
|
||||||
|
if not longitude or not latitude:
|
||||||
|
return qs.none()
|
||||||
|
point = Point(x=float(longitude), y=float(latitude), srid=settings.GEO_DEFAULT_SRID)
|
||||||
|
return qs.last_reviewed(point=point)
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -327,15 +327,30 @@ FCM_DJANGO_SETTINGS = {
|
||||||
|
|
||||||
# Thumbnail settings
|
# Thumbnail settings
|
||||||
THUMBNAIL_ALIASES = {
|
THUMBNAIL_ALIASES = {
|
||||||
'': {
|
'news_preview': {
|
||||||
'tiny': {'size': (100, 0), },
|
'web': {'size': (300, 260), }
|
||||||
'small': {'size': (480, 0), },
|
},
|
||||||
'middle': {'size': (700, 0), },
|
'news_promo_horizontal': {
|
||||||
'large': {'size': (1500, 0), },
|
'web': {'size': (1900, 600), },
|
||||||
'default': {'size': (300, 200), 'crop': True},
|
'mobile': {'size': (375, 260), },
|
||||||
'gallery': {'size': (240, 160), 'crop': True},
|
},
|
||||||
'establishment_preview': {'size': (300, 280), 'crop': True},
|
'news_tile_horizontal': {
|
||||||
}
|
'web': {'size': (300, 275), },
|
||||||
|
'mobile': {'size': (343, 180), },
|
||||||
|
},
|
||||||
|
'news_tile_vertical': {
|
||||||
|
'web': {'size': (300, 380), },
|
||||||
|
},
|
||||||
|
'news_highlight_vertical': {
|
||||||
|
'web': {'size': (460, 630), },
|
||||||
|
},
|
||||||
|
'news_editor': {
|
||||||
|
'web': {'size': (940, 430), }, # при загрузке через контент эдитор
|
||||||
|
'mobile': {'size': (343, 260), }, # через контент эдитор в мобильном браузерe
|
||||||
|
},
|
||||||
|
'avatar_comments': {
|
||||||
|
'web': {'size': (116, 116), },
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Password reset
|
# Password reset
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user