diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 5331ac6e..e4087b4b 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -254,8 +254,6 @@ class EstablishmentQuerySet(models.QuerySet): if establishment.establishment_subtypes.exists(): filters.update( {'establishment_subtypes__in': establishment.establishment_subtypes.all()}) - if establishment.address and establishment.address.coordinates: - qs = qs.annotate_distance(point=establishment.location) return qs def similar_base_subquery(self, establishment, filters: dict) -> Subquery: @@ -269,7 +267,8 @@ class EstablishmentQuerySet(models.QuerySet): .filter(**filters) if establishment.address and establishment.address.coordinates: return Subquery( - qs.order_by('distance') + qs.annotate_distance(point=establishment.location) + .order_by('distance') .distinct() .values_list('id', flat=True)[:settings.LIMITING_QUERY_OBJECTS] ) @@ -292,10 +291,10 @@ class EstablishmentQuerySet(models.QuerySet): } ) return self.filter(id__in=ids_by_subquery.queryset) \ - .annotate_intermediate_public_mark() \ - .annotate_mark_similarity(mark=restaurant.public_mark) \ - .order_by('mark_similarity') \ - .distinct('mark_similarity', 'id') + .annotate_intermediate_public_mark() \ + .annotate_mark_similarity(mark=restaurant.public_mark) \ + .order_by('mark_similarity') \ + .distinct('mark_similarity', 'id') def same_subtype(self, establishment): """Annotate flag same subtype.""" @@ -313,19 +312,19 @@ class EstablishmentQuerySet(models.QuerySet): Return QuerySet with objects that similar to Artisan/Producer(s). :param establishment: Establishment instance """ + base_qs = self.similar_base(establishment).same_subtype(establishment) similarity_rules = { 'ordering': [F('same_subtype').desc(), ], 'distinctions': ['same_subtype', ] } if establishment.address and establishment.address.coordinates: + base_qs = base_qs.annotate_distance(point=establishment.location) similarity_rules['ordering'].append(F('distance').asc()) similarity_rules['distinctions'].append('distance') - return self.similar_base(establishment) \ - .same_subtype(establishment) \ - .has_published_reviews() \ - .order_by(*similarity_rules['ordering']) \ - .distinct(*similarity_rules['distinctions'], 'id') + return base_qs.has_published_reviews() \ + .order_by(*similarity_rules['ordering']) \ + .distinct(*similarity_rules['distinctions'], 'id') def by_wine_region(self, wine_region): """ @@ -346,6 +345,7 @@ class EstablishmentQuerySet(models.QuerySet): Return QuerySet with objects that similar to Winery. :param winery: Establishment instance """ + base_qs = self.similar_base(winery) similarity_rules = { 'ordering': [F('wine_origins__wine_region').asc(), F('wine_origins__wine_sub_region').asc()], @@ -353,13 +353,50 @@ class EstablishmentQuerySet(models.QuerySet): 'wine_origins__wine_sub_region'] } if winery.address and winery.address.coordinates: + base_qs = base_qs.annotate_distance(point=winery.location) similarity_rules['ordering'].append(F('distance').asc()) similarity_rules['distinctions'].append('distance') - return self.similar_base(winery) \ - .order_by(*similarity_rules['ordering']) \ - .distinct(*similarity_rules['distinctions'], - 'id') + return base_qs.order_by(*similarity_rules['ordering']) \ + .distinct(*similarity_rules['distinctions'], 'id') + + def similar_distilleries(self, distillery): + """ + Return QuerySet with objects that similar to Distillery. + :param distillery: Establishment instance + """ + base_qs = self.similar_base(distillery).same_subtype(distillery) + similarity_rules = { + 'ordering': [F('same_subtype').desc(), ], + 'distinctions': ['same_subtype', ] + } + if distillery.address and distillery.address.coordinates: + base_qs = base_qs.annotate_distance(point=distillery.location) + similarity_rules['ordering'].append(F('distance').asc()) + similarity_rules['distinctions'].append('distance') + + return base_qs.published() \ + .has_published_reviews() \ + .order_by(*similarity_rules['ordering']) \ + .distinct(*similarity_rules['distinctions'], 'id') + + def similar_food_producers(self, distillery): + """ + Return QuerySet with objects that similar to Food Producer. + :param distillery: Establishment instance + """ + base_qs = self.similar_base(distillery).same_subtype(distillery) + similarity_rules = { + 'ordering': [F('same_subtype').desc(), ], + 'distinctions': ['same_subtype', ] + } + if distillery.address and distillery.address.coordinates: + base_qs = base_qs.annotate_distance(point=distillery.location) + similarity_rules['ordering'].append(F('distance').asc()) + similarity_rules['distinctions'].append('distance') + + return base_qs.order_by(*similarity_rules['ordering']) \ + .distinct(*similarity_rules['distinctions'], 'id') def last_reviewed(self, point: Point): """ diff --git a/apps/establishment/urls/common.py b/apps/establishment/urls/common.py index 54944a0a..27c0d83d 100644 --- a/apps/establishment/urls/common.py +++ b/apps/establishment/urls/common.py @@ -9,7 +9,8 @@ urlpatterns = [ path('', views.EstablishmentListView.as_view(), name='list'), path('recent-reviews/', views.EstablishmentRecentReviewListView.as_view(), name='recent-reviews'), - path('slug//comments/', views.EstablishmentCommentListView.as_view(), name='list-comments'), + path('slug//comments/', views.EstablishmentCommentListView.as_view(), + name='list-comments'), path('slug//comments/create/', views.EstablishmentCommentCreateView.as_view(), name='create-comment'), path('slug//comments//', views.EstablishmentCommentRUDView.as_view(), @@ -22,9 +23,15 @@ urlpatterns = [ name='similar-restaurants'), path('slug//similar/wineries/', views.WinerySimilarListView.as_view(), name='similar-wineries'), - # temporary uses single mechanism, bec. description in process + path('slug//similar/artisans/', views.ArtisanProducerSimilarListView.as_view(), name='similar-artisans'), + path('slug//similar/artisans/distilleries/', + views.DistillerySimilarListView.as_view(), + name='similar-distilleries'), + path('slug//similar/producers/', views.ArtisanProducerSimilarListView.as_view(), name='similar-producers'), + path('slug//similar/producers/food/', views.FoodProducerSimilarListView.as_view(), + name='similar-food-producers'), ] diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index b4e6f776..e2c8fa5e 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -139,10 +139,38 @@ class ArtisanProducerSimilarListView(EstablishmentSimilarView): return qs.none() +class DistillerySimilarListView(EstablishmentSimilarView): + """Resource for getting a list of similar distillery(s).""" + + def get_queryset(self): + """Overridden get_queryset method""" + qs = super(DistillerySimilarListView, self).get_queryset() + base_establishment = self.get_base_object() + + if base_establishment: + return qs.similar_distilleries(base_establishment)[:settings.QUERY_OUTPUT_OBJECTS] + else: + return qs.none() + + +class FoodProducerSimilarListView(EstablishmentSimilarView): + """Resource for getting a list of similar food producers(s).""" + + def get_queryset(self): + """Overridden get_queryset method""" + qs = super(FoodProducerSimilarListView, self).get_queryset() + base_establishment = self.get_base_object() + + if base_establishment: + return qs.similar_food_producers(base_establishment)[:settings.QUERY_OUTPUT_OBJECTS] + else: + return qs.none() + + class EstablishmentTypeListView(generics.ListAPIView): """Resource for getting a list of establishment types.""" - permission_classes = (permissions.AllowAny,) + permission_classes = (permissions.AllowAny, ) serializer_class = serializers.EstablishmentTypeBaseSerializer queryset = models.EstablishmentType.objects.all()