"""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 CommentRUDSerializer from product import filters, serializers from product.models import Product, ProductType from utils.views import FavoritesCreateDestroyMixinView from utils.pagination import PortionPagination from django.conf import settings 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.ProductCommentCreateSerializer def get_queryset(self): """Override get_queryset method""" product = get_object_or_404(Product, slug=self.kwargs['slug']) return product.comments.order_by('-created') class ProductCommentRUDView(generics.RetrieveUpdateDestroyAPIView): """View for retrieve/update/destroy product comment.""" serializer_class = CommentRUDSerializer 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.similar(base_product)[:settings.QUERY_OUTPUT_OBJECTS] else: return qs.none()