I'm trying to display the chapters of the bible using the bible package available here. Some of the codes are deprecated and I have refactored some. I have the JSON file of the bible loaded in my database. I'm also able to display a list of the books of the Bible.
The problem is how to display the chapters of each book by clicking on the name of the book (which is a link). I have tried the following:
models.py
from django.db import models
from .managers import BookManager
class Book(models.Model):
"""
Book of the Bible
"""
number = models.PositiveIntegerField(primary_key=True, unique=True,
db_index=True)
slug = models.SlugField(unique=True)
name = models.CharField(max_length=64, db_index=True)
is_new_testament = models.BooleanField()
objects = BookManager()
def get_absolute_url(self):
"""
Returns the absolute url
"""
return reverse('book_detail', [self.slug,])
def __unicode__(self):
return self.name
class Meta:
ordering = ['number',]
class Chapter(models.Model):
"""
Chapter of the Bible
"""
book = models.ForeignKey(Book, related_name='chapters', on_delete=models.CASCADE)
number = models.PositiveIntegerField(db_index=True)
def __unicode__(self):
return '%s %s' % (self.book.name, self.number)
def get_next_chapter(self):
try:
return Chapter.objects.filter(
book=self.book,number__gt=self.number).order_by(
'number')[0]
except IndexError:
return None
def get_previous_chapter(self):
try:
return Chapter.objects.filter(
book=self.book,number__lt=self.number).order_by(
'-number')[0]
except IndexError:
return None
def get_absolute_url(self):
"""
Returns the absolute url
"""
return reverse('chapter_detail', [self.book.slug, self.number])
class Meta:
ordering = ['number',]
unique_together=(('book','number',),)
views.py
from django.http import HttpResponse, Http404
from .models import Book, Chapter, Verse
from django.shortcuts import render
from .context_processors import books_processor, book_processor, \
chapter_processor
def book_index(request):
"""Show all books of the Bible."""
books = Book.objects.order_by('number')
context = {'books': books}
return render(request, "bible/book_index.html", context)
def book_detail(request, slug):
"""Show a single book and all its chapters."""
book = Book.objects.get(id=chapter_id)
chapters = book.chapter_set.order_by('number')
context = {'book': book, 'chapters': chapters}
return render(request, 'bible/book_detail.html', context)
Template
{% extends 'app/base.html' %}
{% block page_header %}
<h2>Chapters</h2>
{% endblock page_header %}
{% block content %}
<h5>{{ book }}</h5>
<ul>
{% for chapter in chapters %}
<li>
<p>{{ chapter.number|linebreaks }}</p>
</li>
{% empty %}
<li>There are no chapters for this book yet.</li>
{% endfor %}
</ul>
{% endblock content %}
urls.py
"""URL patterns for bible."""
from django.urls import path
from . import views
app_name = 'bible'
urlpatterns = [
# Home page
path('book_index/', views.book_index, name='book_index'),
# Other pages
path('book_detail/<int:chapter_id>/', views.book_detail, name='book_detail'),
]
The books displays well but when I try to show the chapters of each book, it throws the error:
Template error:
In template... error at line 13
Reverse for 'book_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['book_detail/(?P<chapter_id>[0-9]+)/\\Z']
3 :
4 : {% block page_header %}
5 : <h2>Books of the Bible</h2>
6 : {% endblock page_header %}
7 :
8 : {% block content %}
9 : <ul>
10 : {% for book in books %}
11 : <li>
12 : <h5>
13 : <a href=" {% url 'bible:book_detail' chapter.id %} ">{{ book.name }}</a>
14 : </h5>
15 : </li>
16 : {% empty %}
17 : <li>
18 : <h5 class="font-italic">No books have been added yet.</h5>
19 : </li>
20 : {% endfor %}
21 : </ul>
22 :
23 : {% endblock content %}
I want to be able to see the list of chapters when I click on a book. I've looked at similar tracebacks on Stack Overflow such as this and that but none seemed to help. Would appreciate any help. Thank you.