Need help about redirecting views in Django (New)

I have posted a question with the same title as this one, everyone can see it from this link

Unfortunately, because that was my first time making a question, some format mistakes were made and that question is closed for the moment. I have edited it and resubmitted for opening again but I don't know how long will that take so I might as well make a new one.

I'm working on a web application for reading novels and currently I'm stuck at a certain part in directing views using urls. I use Django as the back end with PostgreSQL as the database and HTML with bootsrap as front end. I will post my code below:

This is my urls.py (from the project folder):

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

This is my urls.py (from the app folder):

from django.contrib import admin
from django.urls import path, include
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
    path('', views.home),
    path('book/<slug:book_slug>/<slug:chapter_slug>/', views.detail, name='detail'),    
    path('genre/<slug:category_slug>', views.category_detail, name='category_detail'),  
    path('book/<slug:book_slug>', views.book_detail, name='book_detail'),
    path('register/', views.register, name="register"),
    path('login/',auth_views.LoginView.as_view(template_name="app/login.html"), name="login"),
    path('logout/',auth_views.LogoutView.as_view(next_page='/'),name='logout'),
]

This is my models.py:

from django.db import models

# Create your models here.
class Category(models.Model):
    name = models.CharField(max_length=50)
    slug = models.SlugField(max_length=50, unique=True, blank=True, editable=True)
    def __str__(self):
        return self.name
class Chapter(models.Model):
    chapter = models.Count
    chapter_name = models.CharField(max_length=100)
    book = models.ForeignKey('Book', on_delete=models.CASCADE, null=True, related_name = 'Books')
    detail = models.TextField()
    slug = models.SlugField(max_length=100, unique=True, blank=True, editable=True)
    def __str__(self):
        return self.chapter_name
class Book(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100, unique=True, blank=True, editable=True)
    cover_image = models.ImageField(upload_to= 'images/', blank= True, null = True)
    author = models.CharField(max_length=100)
    summary = models.TextField()
    category = models.ForeignKey('Category', on_delete=models.CASCADE, null = True, related_name = 'books')
    #date = models.DateField(auto_now_add=True)
    recommended_book = models.BooleanField(default=False)
    recommended_book_hot = models.BooleanField(default=False)
    recommended_book_new = models.BooleanField(default=False)
    recommended_book_finish = models.BooleanField(default=False)
    def __str__(self):
        return self.title

My views.py:

from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from .forms import RegistrationForm
from .models import Book, Category, Chapter
from gtts import gTTS
from django.urls import reverse
from django.shortcuts import get_object_or_404
# Create your views here.
def home(request):
    recommended_book = Book.objects.filter(recommended_book = True)
    recommended_book_hot = Book.objects.filter(recommended_book_hot = True)
    recommended_book_new = Book.objects.filter(recommended_book_new = True)
    recommended_book_finish = Book.objects.filter(recommended_book_finish = True)
    return render(request, 'app/home.html', {'recommended_book': recommended_book, 'recommended_book_hot': recommended_book_hot, 'recommended_book_new': recommended_book_new, 'recommended_book_finish': recommended_book_finish})
def detail(request, book_slug, chapter_slug):
    book = get_object_or_404(Chapter, book__slug = book_slug,slug = chapter_slug)
    title = Book.slug
    return render(request, 'app/detail.html', {'detail': book, 'title':title})
def register(request):
    form = RegistrationForm()
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/')
    return render(request, 'app/register.html', {'form': form})
def category_detail(request, category_slug):
    category = Category.objects.get(slug = category_slug)
    books = Category.objects.prefetch_related('books')
    return render(request, 'app/genre_detail.html', {'category':category})
def book_detail(request, book_slug):
    book = Book.objects.get(slug = book_slug)
    book_category = book.category.first()
    similar_books = Book.objects.filter(category__name__startswith = book_category)
    return render(request, 'app/book_detail.html', {'book': book, 'similar_books': similar_books, 'book_category': book_category})

With the configurations in urls.py, I have managed to go from homepage to a specific novel index page with the url: localhost:8000/book/book.slug then read a chapter using urL:localhost:8000/book/book.slug/chapter.slug, I then place an HTML link to go back to the index page in case I want to stop reading the chapter that goes like this:

 <div class="container p-2">
                <a href="/ " class="text-dark">Home  </a>/
                <a href="{%url 'book_detail' title%}" class="text-dark">{{detail.book}}</a>/
                <a href="" class="text-dark">{{detail.chapter_name}}</a>
            </div>

This is where I'm met with issues as what I have in mind was that when clicked, the link will lead to the index page again which is localhost:8000/book/book.slug. But what actually happened was that it showed a NoReveseMatch error.

From what I can inferred after seeing the logs, there should have been a slug as an argument for the view Book_detail() to work, such as 'test' (slug for a novel name "Test"). But instead, the argument show a blank '('',)' which made the link failed to direct to Book_detail().

Does anyone know what I did wrong ? Any helps or suggestions are appreciated

Change this to:

<a href="{%url 'book_detail' book.slug %}" class="text-dark">{{detail.book}}</a>/
            

Thanks to the answers, I have changed the code a bit in the views.py where title = Book.slug is changed into title = book.slug which fix the error now. But now that the chapter page has loaded properly again, clicking on the url will return me a DoesNotExist at book/chapter.slug error where it explain that "Book matching does not exist". Does this mean the problem now come from models.py instead ?

Try this

<a href="{%url 'book_detail' book__slug.slug %}" class="text-dark">{{detail`.book}}</a>

The problem about DoesNotExist has been fixed !

I found out that by adding another definition in views.py at detail() that goes like this:

def detail(request, book_slug, chapter_slug):
    book = get_object_or_404(Chapter, book__slug = book_slug,slug = chapter_slug)
    index = Book.objects.get(slug = book_slug)
    title = index.slug
    return render(request, 'app/detail.html', {'detail': book, 'title':title})

then add it to the HTML like this:

<div class="container p-2">
                <a href="/ " class="text-dark">Home  </a>/
                <a href="{%url 'book_detail' title%}" class="text-dark">{{detail.book}}</a>/
                <a href="" class="text-dark">{{detail.chapter_name}}</a>
            </div>

I can now return to the Index page !

Thank you, everyone, for your helps and suggestions. I have also realized that a lot of clumsy mistakes were made and they weren't really that hard to solve, actually. It's just that I overlooked them.

Back to Top