"""Product app views.""" from django.conf import settings from django.shortcuts import get_object_or_404 from rest_framework import generics, permissions from comment.models import Comment from comment.serializers import CommentBaseSerializer from product import filters, serializers from product.models import Product, ProductType from utils.views import FavoritesCreateDestroyMixinView class ProductBaseView(generics.GenericAPIView): """Product base view""" permission_classes = (permissions.AllowAny,) def get_queryset(self): """Override get_queryset method.""" return Product.objects.published() \ .with_base_related() \ .annotate_in_favorites(self.request.user) \ .order_by('-created') class ProductListView(ProductBaseView, generics.ListAPIView): """List view for model Product.""" serializer_class = serializers.ProductBaseSerializer filter_class = filters.ProductFilterSet def get_queryset(self): qs = super().get_queryset().with_extended_related() \ .by_country_code(self.request.country_code) return qs class ProductSimilarView(ProductListView): """Resource for getting a list of similar product.""" serializer_class = serializers.ProductBaseSerializer pagination_class = None def get_base_object(self): """ Return base product instance for a getting list of similar products. """ find_by = { 'slug': self.kwargs.get('slug'), } if isinstance(self.kwargs.get('type'), str): if not self.kwargs.get('type') in ProductType.INDEX_PLURAL_ONE: return None find_by['product_type'] = get_object_or_404(ProductType.objects.all(), index_name=ProductType.INDEX_PLURAL_ONE[self.kwargs.get('type')]) product = get_object_or_404(Product.objects.all(), **find_by) return product class ProductDetailView(ProductBaseView, generics.RetrieveAPIView): """Detail view fro model Product.""" lookup_field = 'slug' serializer_class = serializers.ProductDetailSerializer class CreateFavoriteProductView(FavoritesCreateDestroyMixinView): """View for create/destroy product in favorites.""" _model = Product serializer_class = serializers.ProductFavoritesCreateSerializer class ProductCommentCreateView(generics.CreateAPIView): """View for create new comment.""" lookup_field = 'slug' serializer_class = serializers.ProductCommentCreateSerializer queryset = Comment.objects.all() class ProductCommentListView(generics.ListAPIView): """View for return list of product comments.""" permission_classes = (permissions.AllowAny,) serializer_class = serializers.ProductCommentBaseSerializer def get_queryset(self): """Override get_queryset method""" product = get_object_or_404(Product, slug=self.kwargs['slug']) return product.comments.public(self.request.user).order_by('-created') class ProductCommentRUDView(generics.RetrieveUpdateDestroyAPIView): """View for retrieve/update/destroy product comment.""" serializer_class = serializers.ProductCommentBaseSerializer queryset = Product.objects.all() def get_object(self): """Returns the object the view is displaying.""" queryset = self.filter_queryset(self.get_queryset()) product_obj = get_object_or_404(queryset, slug=self.kwargs['slug']) comment_obj = get_object_or_404(product_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 SimilarListView(ProductSimilarView): """Return similar products.""" def get_queryset(self): """Overridden get_queryset method.""" qs = super(SimilarListView, self).get_queryset() base_product = self.get_base_object() if base_product: return qs.has_location().similar(base_product)[:settings.QUERY_OUTPUT_OBJECTS] else: return qs.none()