Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProductRetrieveView:param:with_direct_siblings if True return product_pre, product_next to the context and direct_siblings in serializer #801

Open
wants to merge 10 commits into
base: releases/1.2
Choose a base branch
from
54 changes: 51 additions & 3 deletions shop/serializers/bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from shop.models.product import ProductModel
from shop.models.order import OrderItemModel
from shop.rest.money import MoneyField

from shop.rest.filters import CMSPagesFilterBackend

class BaseCustomerSerializer(serializers.ModelSerializer):
number = serializers.CharField(source='get_number')
Expand Down Expand Up @@ -44,11 +44,59 @@ class ProductSerializer(serializers.ModelSerializer):

class Meta:
model = ProductModel
direct_siblings = None
fields = '__all__'

def __init__(self, *args, **kwargs):
def __init__(self, product, *args, **kwargs):
kwargs.setdefault('label', 'catalog')
super(ProductSerializer, self).__init__(*args, **kwargs)
super(ProductSerializer, self).__init__(product, *args, **kwargs)
if 'view' in kwargs['context'] and 'with_direct_siblings' in kwargs['context'][
'view'].kwargs and kwargs['context']['view'].kwargs['with_direct_siblings']:
self.prev, self.next = self.get_object_with_direct_siblings(
product, kwargs['context']['request'])
self.request = kwargs['context']['request']
self.fields['direct_siblings'] = serializers.SerializerMethodField(
'serializer_direct_siblings')
self.Meta.direct_siblings = self.prev, self.next

def serializer_direct_siblings(self, product, previous=None, next=None):
if self.prev:
previous = {
"product_name": self.prev.product_name,
"slug": self.prev.slug,
"img_name": self.prev.images.first().original_filename,
"img_url": self.prev.images.first().url}
if self.next:
next = {
"product_name": self.next.product_name,
"slug": self.next.slug,
"img_name": self.next.images.first().original_filename,
"img_url": self.next.images.first().url}
return previous, next

def get_object_with_direct_siblings(self, product, request=None):
if not request:
request = self.request

if not hasattr(self, '_product_direct_siblings'):
previous = next = None
filter_siblings = {
'active': True,
}
if hasattr(ProductModel, 'translations'):
filter_siblings.update(
translations__language_code=get_language_from_request(request))
queryset = ProductModel.objects.filter(**filter_siblings)
queryset = CMSPagesFilterBackend().filter_queryset(request, queryset, self)
nb = queryset.count()
for index, obj in enumerate(queryset):
if obj.slug == product.slug:
if index > 0:
previous = queryset[index - 1]
if index < (nb - 1):
next = queryset[index + 1]
self._product_direct_siblings = previous, next
return self._product_direct_siblings

def get_price(self, product):
price = product.get_price(self.context['request'])
Expand Down
29 changes: 22 additions & 7 deletions shop/views/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ class ProductRetrieveView(generics.RetrieveAPIView):

:param use_modal_dialog: If ``True`` (default), render a modal dialog to confirm adding the
product to the cart.

:param with_direct_siblings: If ``True`` (no default), product_prev, product_next are added to the context.
"""

renderer_classes = (ShopTemplateHTMLRenderer, JSONRenderer, BrowsableAPIRenderer)
Expand All @@ -267,6 +269,7 @@ class ProductRetrieveView(generics.RetrieveAPIView):
serializer_class = ProductSerializer
limit_choices_to = models.Q()
use_modal_dialog = True
with_direct_siblings = False

def dispatch(self, request, *args, **kwargs):
"""
Expand All @@ -282,6 +285,7 @@ def dispatch(self, request, *args, **kwargs):
namespaces, this method first attempts to resolve by product, and if that fails, it
forwards the request to django-CMS.
"""
kwargs['with_direct_siblings'] = self.with_direct_siblings
try:
return super(ProductRetrieveView, self).dispatch(request, *args, **kwargs)
except Http404:
Expand All @@ -290,7 +294,7 @@ def dispatch(self, request, *args, **kwargs):
else:
is_root = request.current_page.node.is_root()
if is_root:
return details(request, kwargs.get('slug'))
return details(request, kwargs.get('slug'), with_direct_siblings=self.with_direct_siblings )
raise
except:
raise
Expand All @@ -309,12 +313,23 @@ def get_renderer_context(self):
renderer_context = super(ProductRetrieveView, self).get_renderer_context()
if renderer_context['request'].accepted_renderer.format == 'html':
# add the product as Python object to the context
product = self.get_object()
renderer_context.update(
app_label=product._meta.app_label.lower(),
product=product,
use_modal_dialog=self.use_modal_dialog,
)
if not self.with_direct_siblings:
product = self.get_object()
renderer_context.update(
app_label=product._meta.app_label.lower(),
product=product,
use_modal_dialog=self.use_modal_dialog,
)
else:
product = self.get_object()
self.product_prev,self.product_next = self.serializer_class.Meta.direct_siblings
renderer_context.update(
app_label=product._meta.app_label.lower(),
product_prev=self.product_prev,
product=product,
product_next=self.product_next,
use_modal_dialog=self.use_modal_dialog,
)
return renderer_context

def get_object(self):
Expand Down