Django function doesn't return HTML page

I'm adding pagination on my website. This is my function:

views.py

def ProductList(request, category_slug=None, page_number=1):
  content = {}
  category = None
  categories = Category.objects.all()
  products = Product.objects.filter(available=True)
  if category_slug:
      category = get_object_or_404(Category, slug=category_slug)
      products = products.filter(category=category)
  current_page = Paginator(products, 2)
  content['category'] = category
  content['categories'] = categories
  content['products'] = current_page.page(page_number)
  return render(request, 'product/list.html', content)

urls.py

urlpatterns = [
    url(r'^$', views.ProductList, name='ProductList'),
    url(r'^page/(\d+)/$', views.ProductList, name='ProductList'),
    url(r'^(?P<category_slug>[-\w]+)/$', views.ProductList, name='ProductListByCategory'),
    url(r'^(?P<id>\d+)/(?P<slug>[-\w]+)/$', views.ProductDetail, name='ProductDetail'),

]

But every time I'm trying to get next page I see this error:

Page not found (404)
Request Method:     GET
Request URL:    http://127.0.0.1:8000/page/2/
Raised by:  shop.views.ProductList

I can't really understand what I'm doing wrong. Thank you.

1 answer

  • answered 2018-04-14 14:28 Daniel Roseman

    You haven't given a name to the group that captures the page number in your regex. So Django passes it to the view as a positional argument, not a keyword argument; and since the first positional argument after request is category_slug, that is the variable the number will be assigned to.

    To fix this, use a named argument, like you do for id later:

    url(r'^page/(?P<page_number>\d+)/$', views.ProductList, name='ProductList'),
    

    Note, though, page number is usually passed as a querystring parameter, rather than in the URL path itself.