4

I was just checking out django, and was trying a view to list the books by passing id as an argument to the URL books/urls.py. But getting 404 page not found error. I'm not getting whats wrong in the url when I typed this url in the browser:

 http://192.168.0.106:8000/books/list/21/

bookstore/urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', include("books.urls"))
] 

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books'
   ]
...
...
...
ROOT_URLCONF = 'bookstore.urls'

books/urls.py

urlpatterns = [
     path('home/', create),
     path('list/(?P<id>\d+)', list_view),
]

books/views.py

def create(request):
    form = CreateForm(request.POST or None, request.FILES or None)
    if form.is_valid():
        instance = form.save(commit=False)
        instance.save()
        messages.success(request, "Book Created")
        return redirect('/books/list', kwargs={"id":instance.id})
    return render(request, "home.html", {"form":form})


def list_view(request, id=None):
    books = Book.objects.filter(id=id)
    return render(request, "list.html", {"books": books})

Project Structure:

├── books
│   ├── admin.py
│   ├── forms.py
│   ├── __init__.py
│   ├── models.py
│   ├── urls.py
│   └── views.py
├── bookstore
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py

Here is the screenshot - 404 Page

EDIT - As addressed in the comments - Tried by appending / in the url expression of thebooks.urls but no luck :( Screenshot

Laxmikant
  • 2,046
  • 3
  • 30
  • 44
  • Using `books = Book.objects.filter(id=id)` looks a little odd. If `id` is the id of the book, I would expect to see `book = Book.objects.get(id=id)`, or possibly `book = get_object_or_404(Book, id=id)`. – Alasdair Nov 16 '17 at 16:25
  • @Alasdair - Actually it was `book_id` and those were duplicates, so replaced it to `id` as a part of testing. – Laxmikant Nov 16 '17 at 16:27
  • 2
    Also, your `redirect` line is incorrectly mixing a hardcoded URL and kwargs. You can either construct the URL with `return redirect('/books/list/%s/' % instance.id)`, or the recommended approach is to let Django reverse the URL with `return redirect('list_view', kwargs={id:instance.id})`. – Alasdair Nov 16 '17 at 16:28
  • @Alasdair - Create is working fine, no issue at all. Stuck only with list view when passed `id` in the urls. Tried typing url manually in the browser as well. – Laxmikant Nov 16 '17 at 16:31
  • Trust me, the `redirect` is incorrect, even if it's not giving you an error. My guess is that the reverse will silently fail and it will redirect to `/books/list/`, ignoring the kwargs. – Alasdair Nov 16 '17 at 16:41
  • @Alasdair - Oh - I will correct it, Thank you – Laxmikant Nov 16 '17 at 16:43

1 Answers1

5

You are using the new path from Django 2.0 incorrectly. You shouldn't use a regex like \d+. Try changing it to:

 path('list/<int:id>/', list_view, name='list_view'),

The name is required if you want to reverse the URL.

If you want to stick with regexes, then use re_path (or url() still works if you want to be compatible with older versions of Django). See the URL dispatcher docs for more info.

Note the trailing slash as well - otherwise your path matches http://192.168.0.106:8000/books/list/21 but not http://192.168.0.106:8000/books/list/21/.

Alasdair
  • 298,606
  • 55
  • 578
  • 516