How can I get pagination for the current code? I can't change the DetailView to View or ListView, so in this class I get a filter of products.
class CategoryDetailView(DetailView):
model = Category
queryset = Category.objects.all()
context_object_name = 'category'
template_name = 'category_products.html'
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
...
products = Product.objects.filter(id__in=[pf_['product_id'] for pf_ in pf])
context['category_products'] = products
return context
Typically one picks the class-based view that is the most convenient to do the job. You can see your view as a ListView
of Product
s that are related to a certain category. By doing this, you make it more convenient to retrieve the related Product
s, and less convenient to obtain the relevant Category
, but the last one is easier.
We can implement the view as:
from django.shortcuts import get_object_or_404
class CategoryDetailView(ListView):
model = Product
context_object_name = 'category_products'
template_name = 'category_products.html'
paginate_by = 1
# …
def get_queryset(self):
qs = super().get_queryset().filter(
category__slug=self.kwargs['slug']
)
qd = self.request.GET.copy()
qd.pop(self.page_kwarg, None)
if 'search' in self.request.GET:
qs = qs.filter(title__icontains=self.request.GET['search'])
elif qd:
qs = qs.filter(
features__value__in=[v for _, vs in qd.lists() for v in vs]
)
if 'sort' in self.request.GET:
qs = qs.order_by(self.request.GET['sort'])
return qs
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['category'] = get_object_or_404(Category, pk=self.kwargs['pk'], slug=self.kwargs['slug'])
return context
The get_queryset
here thus implements the advanced querying you implemented, and we add the category
by overriding the get_queryset
. This queryset will then automatically get paginated by the logic of the ListView
.
I would however advise to simplify the logic, usually advanced filtering only makes it more error prone. Furthermore ordering by an arbitrary parameter introduces a security vulnerability, one could for example try to filter on some_foreignkey__some_secure_field
to expose data. You thus might want to validate that the order
is in a list of acceptable values.