"""Establishment app views.""" from django.conf import settings from django.contrib.gis.geos import Point from django.shortcuts import get_object_or_404 from rest_framework import generics, permissions from comment import models as comment_models from establishment import filters from establishment import models, serializers from main import methods from main.models import MetaDataContent from utils.pagination import EstablishmentPortionPagination class EstablishmentMixinView: """Establishment mixin.""" permission_classes = (permissions.AllowAny,) def get_queryset(self): """Overridden method 'get_queryset'.""" return models.Establishment.objects.published() \ .with_base_related() \ .annotate_in_favorites(self.request.user) class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView): """Resource for getting a list of establishments.""" filter_class = filters.EstablishmentFilter serializer_class = serializers.EstablishmentBaseSerializer def get_queryset(self): """Overridden method 'get_queryset'.""" qs = super(EstablishmentListView, self).get_queryset() if self.request.country_code: qs = qs.by_country_code(self.request.country_code) return qs class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView): """Resource for getting a establishment.""" lookup_field = 'slug' serializer_class = serializers.EstablishmentDetailSerializer def get_queryset(self): return super().get_queryset().with_extended_related() 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): """Resource for getting a list of establishments.""" serializer_class = serializers.EstablishmentBaseSerializer pagination_class = EstablishmentPortionPagination def get_queryset(self): """Override get_queryset method""" qs = super().get_queryset() return qs.similar(establishment_slug=self.kwargs.get('slug')) class EstablishmentTypeListView(generics.ListAPIView): """Resource for getting a list of establishment types.""" permission_classes = (permissions.AllowAny,) serializer_class = serializers.EstablishmentTypeSerializer queryset = models.EstablishmentType.objects.all() class EstablishmentCommentCreateView(generics.CreateAPIView): """View for create new comment.""" lookup_field = 'slug' serializer_class = serializers.EstablishmentCommentCreateSerializer queryset = comment_models.Comment.objects.all() class EstablishmentCommentListView(generics.ListAPIView): """View for return list of establishment comments.""" permission_classes = (permissions.AllowAny,) serializer_class = serializers.EstablishmentCommentCreateSerializer def get_queryset(self): """Override get_queryset method""" establishment = get_object_or_404(models.Establishment, slug=self.kwargs['slug']) return comment_models.Comment.objects.by_content_type(app_label='establishment', model='establishment')\ .by_object_id(object_id=establishment.pk)\ .order_by('-created') class EstablishmentCommentRUDView(generics.RetrieveUpdateDestroyAPIView): """View for retrieve/update/destroy establishment comment.""" serializer_class = serializers.EstablishmentCommentRUDSerializer queryset = models.Establishment.objects.all() def get_object(self): """ Returns the object the view is displaying. """ queryset = self.filter_queryset(self.get_queryset()) establishment_obj = get_object_or_404(queryset, slug=self.kwargs['slug']) comment_obj = get_object_or_404(establishment_obj.comments.by_user(self.request.user), pk=self.kwargs['comment_id']) # May raise a permission denied self.check_object_permissions(self.request, comment_obj) return comment_obj class EstablishmentFavoritesCreateDestroyView(generics.CreateAPIView, generics.DestroyAPIView): """View for create/destroy establishment from favorites.""" serializer_class = serializers.EstablishmentFavoritesCreateSerializer lookup_field = 'slug' def get_object(self): """ Returns the object the view is displaying. """ establishment_obj = get_object_or_404(models.Establishment, slug=self.kwargs['slug']) obj = get_object_or_404( self.request.user.favorites.by_content_type(app_label='establishment', model='establishment') .by_object_id(object_id=establishment_obj.pk)) # May raise a permission denied self.check_object_permissions(self.request, obj) return obj class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIView): """Resource for getting list of nearest establishments.""" serializer_class = serializers.EstablishmentBaseSerializer filter_class = filters.EstablishmentFilter def get_queryset(self): """Overridden method 'get_queryset'.""" # todo: latitude and longitude lat = self.request.query_params.get('lat') lon = self.request.query_params.get('lon') radius = self.request.query_params.get('radius') unit = self.request.query_params.get('unit') qs = super(EstablishmentNearestRetrieveView, self).get_queryset() if lat and lon and radius and unit: center = Point(float(lat), float(lon)) filter_kwargs = {'center': center, 'radius': float(radius), 'unit': unit} return qs.by_distance_from_point(**{k: v for k, v in filter_kwargs.items() if v is not None}) return qs class EstablishmentTagListView(generics.ListAPIView): """List view for establishment tags.""" serializer_class = serializers.EstablishmentTagListSerializer permission_classes = (permissions.AllowAny,) pagination_class = None def get_queryset(self): """Override get_queryset method""" return MetaDataContent.objects.by_content_type(app_label='establishment', model='establishment')\ .distinct('metadata__label')