Merge branch 'develop' into feature/permission_liquor
This commit is contained in:
commit
e3cf808e3d
|
|
@ -24,8 +24,8 @@ from collection.models import Collection
|
|||
from location.models import Address
|
||||
from location.models import WineOriginAddressMixin
|
||||
from main.models import Award, Currency
|
||||
from tag.models import Tag
|
||||
from review.models import Review
|
||||
from tag.models import Tag
|
||||
from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
|
||||
TranslatedFieldsMixin, BaseAttributes, GalleryModelMixin,
|
||||
IntermediateGalleryModelMixin, HasTagsMixin,
|
||||
|
|
@ -209,23 +209,34 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
"""
|
||||
return self.annotate(mark_similarity=ExpressionWrapper(
|
||||
mark - F('intermediate_public_mark'),
|
||||
output_field=models.FloatField()
|
||||
output_field=models.FloatField(default=0)
|
||||
))
|
||||
|
||||
def similar(self, establishment_slug: str):
|
||||
def similar_base(self, establishment):
|
||||
|
||||
filters = {
|
||||
'reviews__status': Review.READY,
|
||||
'establishment_type': establishment.establishment_type,
|
||||
}
|
||||
if establishment.establishment_subtypes.exists():
|
||||
filters.update({'establishment_subtypes__in': establishment.establishment_subtypes.all()})
|
||||
return self.exclude(id=establishment.id) \
|
||||
.filter(**filters) \
|
||||
.annotate_distance(point=establishment.location)
|
||||
|
||||
def similar_restaurants(self, slug):
|
||||
"""
|
||||
Return QuerySet with objects that similar to Establishment.
|
||||
:param establishment_slug: str Establishment slug
|
||||
Return QuerySet with objects that similar to Restaurant.
|
||||
:param restaurant_slug: str Establishment slug
|
||||
"""
|
||||
establishment_qs = self.filter(slug=establishment_slug,
|
||||
public_mark__isnull=False)
|
||||
if establishment_qs.exists():
|
||||
establishment = establishment_qs.first()
|
||||
restaurant_qs = self.filter(slug=slug,
|
||||
public_mark__isnull=False)
|
||||
if restaurant_qs.exists():
|
||||
establishment = restaurant_qs.first()
|
||||
subquery_filter_by_distance = Subquery(
|
||||
self.exclude(slug=establishment_slug)
|
||||
.filter(image_url__isnull=False, public_mark__gte=10)
|
||||
.has_published_reviews()
|
||||
.annotate_distance(point=establishment.location)
|
||||
self.similar_base(establishment)
|
||||
.filter(public_mark__gte=10,
|
||||
establishment_gallery__is_main=True)
|
||||
.order_by('distance')[:settings.LIMITING_QUERY_OBJECTS]
|
||||
.values('id')
|
||||
)
|
||||
|
|
@ -234,6 +245,36 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
.annotate_mark_similarity(mark=establishment.public_mark) \
|
||||
.order_by('mark_similarity') \
|
||||
.distinct('mark_similarity', 'id')
|
||||
|
||||
def by_wine_region(self, wine_region):
|
||||
"""
|
||||
Return filtered QuerySet by wine region in wine origin.
|
||||
:param wine_region: wine region.
|
||||
"""
|
||||
return self.filter(wine_origin__wine_region=wine_region).distinct()
|
||||
|
||||
def by_wine_sub_region(self, wine_sub_region):
|
||||
"""
|
||||
Return filtered QuerySet by wine region in wine origin.
|
||||
:param wine_sub_region: wine sub region.
|
||||
"""
|
||||
return self.filter(wine_origin__wine_sub_region=wine_sub_region).distinct()
|
||||
|
||||
def similar_wineries(self, slug: str):
|
||||
"""
|
||||
Return QuerySet with objects that similar to Winery.
|
||||
:param establishment_slug: str Establishment slug
|
||||
"""
|
||||
winery_qs = self.filter(slug=slug)
|
||||
if winery_qs.exists():
|
||||
winery = winery_qs.first()
|
||||
return self.similar_base(winery) \
|
||||
.order_by(F('wine_origins__wine_region').asc(),
|
||||
F('wine_origins__wine_sub_region').asc()) \
|
||||
.annotate_distance(point=winery.location) \
|
||||
.order_by('distance') \
|
||||
.distinct('distance', 'wine_origins__wine_region',
|
||||
'wine_origins__wine_sub_region', 'id')
|
||||
else:
|
||||
return self.none()
|
||||
|
||||
|
|
@ -457,15 +498,9 @@ 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']) \
|
||||
.exclude(value__in=['rss', 'rss_selection'])
|
||||
'business_tag', 'business_tags_de', 'tag'])
|
||||
# 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:
|
||||
|
|
@ -830,6 +865,25 @@ class ContactEmail(models.Model):
|
|||
return f'{self.email}'
|
||||
|
||||
|
||||
#
|
||||
# class Wine(TranslatedFieldsMixin, models.Model):
|
||||
# """Wine model."""
|
||||
# establishment = models.ForeignKey(
|
||||
# 'establishment.Establishment', verbose_name=_('establishment'),
|
||||
# on_delete=models.CASCADE)
|
||||
# bottles = models.IntegerField(_('bottles'))
|
||||
# price_min = models.DecimalField(
|
||||
# _('price min'), max_digits=14, decimal_places=2)
|
||||
# price_max = models.DecimalField(
|
||||
# _('price max'), max_digits=14, decimal_places=2)
|
||||
# by_glass = models.BooleanField(_('by glass'))
|
||||
# price_glass_min = models.DecimalField(
|
||||
# _('price min'), max_digits=14, decimal_places=2)
|
||||
# price_glass_max = models.DecimalField(
|
||||
# _('price max'), max_digits=14, decimal_places=2)
|
||||
#
|
||||
|
||||
|
||||
class Plate(TranslatedFieldsMixin, models.Model):
|
||||
"""Plate model."""
|
||||
STR_FIELD_NAME = 'name'
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ urlpatterns = [
|
|||
path('', views.EstablishmentListView.as_view(), name='list'),
|
||||
path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(),
|
||||
name='recent-reviews'),
|
||||
path('slug/<slug:slug>/similar/', views.EstablishmentSimilarListView.as_view(), name='similar'),
|
||||
path('slug/<slug:slug>/comments/', views.EstablishmentCommentListView.as_view(), name='list-comments'),
|
||||
path('slug/<slug:slug>/comments/create/', views.EstablishmentCommentCreateView.as_view(),
|
||||
name='create-comment'),
|
||||
|
|
@ -17,4 +16,11 @@ urlpatterns = [
|
|||
name='rud-comment'),
|
||||
path('slug/<slug:slug>/favorites/', views.EstablishmentFavoritesCreateDestroyView.as_view(),
|
||||
name='create-destroy-favorites'),
|
||||
|
||||
# similar establishments
|
||||
path('slug/<slug:slug>/similar/', views.RestaurantSimilarListView.as_view(),
|
||||
name='similar-restaurants'),
|
||||
path('slug/<slug:slug>/similar/wineries/', views.WinerySimilarListView.as_view(),
|
||||
name='similar-restaurants'),
|
||||
|
||||
]
|
||||
|
|
|
|||
|
|
@ -77,16 +77,28 @@ class EstablishmentRecentReviewListView(EstablishmentListView):
|
|||
return qs.last_reviewed(point=point)
|
||||
|
||||
|
||||
class EstablishmentSimilarListView(EstablishmentListView):
|
||||
"""Resource for getting a list of establishments."""
|
||||
|
||||
class EstablishmentSimilarList(EstablishmentListView):
|
||||
"""Resource for getting a list of similar establishments."""
|
||||
serializer_class = serializers.EstablishmentSimilarSerializer
|
||||
pagination_class = EstablishmentPortionPagination
|
||||
|
||||
|
||||
class RestaurantSimilarListView(EstablishmentSimilarList):
|
||||
"""Resource for getting a list of similar restaurants."""
|
||||
|
||||
def get_queryset(self):
|
||||
"""Override get_queryset method"""
|
||||
qs = super().get_queryset()
|
||||
return qs.similar(establishment_slug=self.kwargs.get('slug'))
|
||||
return EstablishmentMixinView.get_queryset(self) \
|
||||
.similar_restaurants(slug=self.kwargs.get('slug'))
|
||||
|
||||
|
||||
class WinerySimilarListView(EstablishmentSimilarList):
|
||||
"""Resource for getting a list of similar wineries."""
|
||||
|
||||
def get_queryset(self):
|
||||
"""Override get_queryset method"""
|
||||
return EstablishmentMixinView.get_queryset(self) \
|
||||
.similar_wineries(slug=self.kwargs.get('slug'))
|
||||
|
||||
|
||||
class EstablishmentTypeListView(generics.ListAPIView):
|
||||
|
|
|
|||
18
apps/news/migrations/0038_news_backoffice_title.py
Normal file
18
apps/news/migrations/0038_news_backoffice_title.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.7 on 2019-12-10 12:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('news', '0037_auto_20191129_1320'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='news',
|
||||
name='backoffice_title',
|
||||
field=models.TextField(default=None, null=True, verbose_name='Title for searching via BO'),
|
||||
),
|
||||
]
|
||||
|
|
@ -168,6 +168,8 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi
|
|||
title = TJSONField(blank=True, null=True, default=None,
|
||||
verbose_name=_('title'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
backoffice_title = models.TextField(null=True, default=None,
|
||||
verbose_name=_('Title for searching via BO'))
|
||||
subtitle = TJSONField(blank=True, null=True, default=None,
|
||||
verbose_name=_('subtitle'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
|
|
|
|||
|
|
@ -169,9 +169,13 @@ class NewsBackOfficeBaseSerializer(NewsBaseSerializer):
|
|||
|
||||
fields = NewsBaseSerializer.Meta.fields + (
|
||||
'title',
|
||||
'backoffice_title',
|
||||
'subtitle',
|
||||
'is_published',
|
||||
)
|
||||
extra_kwargs = {
|
||||
'backoffice_title': {'allow_null': False},
|
||||
}
|
||||
|
||||
|
||||
class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class NewsDocument(Document):
|
|||
'name': fields.KeywordField()})
|
||||
title = fields.ObjectField(attr='title_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES)
|
||||
backoffice_title = fields.TextField(analyzer='english')
|
||||
subtitle = fields.ObjectField(attr='subtitle_indexing',
|
||||
properties=OBJECT_FIELD_PROPERTIES)
|
||||
description = fields.ObjectField(attr='description_indexing',
|
||||
|
|
|
|||
|
|
@ -314,7 +314,8 @@ class MobileEstablishmentDocumentViewSet(EstablishmentDocumentViewSet):
|
|||
filter_backends = [
|
||||
FilteringFilterBackend,
|
||||
filters.CustomSearchFilterBackend,
|
||||
GeoSpatialFilteringFilterBackend,
|
||||
filters.CustomGeoSpatialFilteringFilterBackend,
|
||||
GeoSpatialOrderingFilterBackend,
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user