.NoReverseMatch: Reverse for 'author-detail' with arguments '(''

ghz 17hours ago ⋅ 5 views

.NoReverseMatch: Reverse for 'author-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['catalog/author/(?P[0-9]+)$']

Many people have already asked similar questions to this, but I still cannot figure out the solution unfortunately. I am doing a Django tutorial from https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website . I compared my code with theirs on GitHub but I do not see any difference. The current state of my code is here https://github.com/diveki/webdev/tree/master/django_projects/locallibrary it works well except for showing the details of the Author model.

The error message I get is: django.urls.exceptions.NoReverseMatch: Reverse for 'author-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['catalog/author/(?P<pk>[0-9]+)$'] .

The full error that django gives when I click on the Author list items:

NoReverseMatch at /catalog/author/1
Reverse for 'author-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['catalog/author/(?P<pk>[0-9]+)$']
Request Method: GET
Request URL:    http://127.0.0.1:8000/catalog/author/1
Django Version: 3.0.4
Exception Type: NoReverseMatch
Exception Value:    
Reverse for 'author-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['catalog/author/(?P<pk>[0-9]+)$']
Exception Location: C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\urls\resolvers.py in _reverse_with_prefix, line 677
Python Executable:  C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\python.exe
Python Version: 3.7.3
Python Path:    
['C:\\Users\\divekizs\\Python\\Scripts\\WebDev\\django_projects\\locallibrary',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django\\python37.zip',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django\\DLLs',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django\\lib',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django\\lib\\site-packages',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django\\lib\\site-packages\\win32',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django\\lib\\site-packages\\win32\\lib',
 'C:\\Users\\divekizs\\AppData\\Local\\Continuum\\anaconda3\\envs\\django\\lib\\site-packages\\Pythonwin']
Server time:    Wed, 18 Mar 2020 18:34:15 +0100

Traceback:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/catalog/author/1

Django Version: 3.0.4
Python Version: 3.7.3
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'catalog']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template C:\Users\divekizs\Python\Scripts\WebDev\django_projects\locallibrary\catalog\templates\base_generic.html, error at line 6
   Reverse for 'author-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['catalog/author/(?P<pk>[0-9]+)$']
   1 : <!DOCTYPE html>
   2 : <html lang="en">
   3 : <head>
   4 :   {% block title %}<title>Local Library</title>{% endblock %}
   5 :   <meta charset="utf-8">
   6 :   <meta name="viewport" co ntent="width=device-width, initial-scale=1" >
   7 :   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
   8 :   <!-- Add additional CSS in static file -->
   9 :   {% load static %}
   10 :   <link rel="stylesheet" href="{% static 'css/styles.css' %}">
   11 : </head>
   12 : <body>
   13 :   <div class="container-fluid">
   14 :     <div class="row">
   15 :       <div class="col-sm-2">
   16 :       {% block sidebar %}


Traceback (most recent call last):
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\core\handlers\base.py", line 145, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\core\handlers\base.py", line 143, in _get_response
    response = response.render()
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\response.py", line 105, in render
    self.content = self.rendered_content
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\response.py", line 83, in rendered_content
    return template.render(context, self._request)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\backends\django.py", line 61, in render
    return self.template.render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 171, in render
    return self._render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 163, in _render
    return self.nodelist.render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 936, in render
    bit = node.render_annotated(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 903, in render_annotated
    return self.render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 163, in _render
    return self.nodelist.render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 936, in render
    bit = node.render_annotated(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 903, in render_annotated
    return self.render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 936, in render
    bit = node.render_annotated(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\base.py", line 903, in render_annotated
    return self.render(context)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\template\defaulttags.py", line 443, in render
    url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\urls\base.py", line 87, in reverse
    return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
  File "C:\Users\divekizs\AppData\Local\Continuum\anaconda3\envs\django\lib\site-packages\django\urls\resolvers.py", line 677, in _reverse_with_prefix
    raise NoReverseMatch(msg)

Exception Type: NoReverseMatch at /catalog/author/1
Exception Value: Reverse for 'author-detail' with arguments '('',)' not found. 1 pattern(s) tried: ['catalog/author/(?P<pk>[0-9]+)$']

I do not copy here all the code I wrote for this (unless you need it), but here is my models.py, urls.py from catalog, the relevant code from views.py and the templates:

Part of my catalog/models.py:

from django.db import models
from django.urls import reverse # Used to generate URLs by reversing the URL patterns
import uuid # Required for unique book instances

class Author(models.Model):
    """Model representing an author."""
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    date_of_birth = models.DateField(null=True, blank=True)
    date_of_death = models.DateField('died', null=True, blank=True)

    class Meta:
        ordering = ['last_name', 'first_name']

    def get_absolute_url(self):
        """Returns the url to access a particular author instance."""
        return reverse('author-detail', args=[str(self.id)])

    def __str__(self):
        """String for representing the Model object."""
        return '{0}, {1}'.format(self.last_name, self.first_name)

catalog/urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('books/', views.BookListView.as_view(), name='books'),
    path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
    path('authors/', views.AuthorListView.as_view(), name='authors'),
    path('author/<int:pk>',
         views.AuthorDetailView.as_view(), name='author-detail'),
]

Complete catalog/views.py:

from django.shortcuts import render
from catalog.models import Book, Author, BookInstance, Genre
from django.views import generic

# Create your views here.
def index(request):
    num_books = Book.objects.all().count()
    num_instances = BookInstance.objects.all().count()

    #Available Books
    num_instances_available = BookInstance.objects.filter(status__exact='a').count()
    num_authors = Author.objects.count()
    biography_num = Book.objects.filter(genre__name__icontains='horror').count()

    context = {
        'filtered': biography_num,
        'title': 'Changed from index view',
        'num_books': num_books,
        'num_instances': num_instances,
        'num_instances_available': num_instances_available,
        'num_authors': num_authors,
    }

    return render(request, 'index.html', context=context)

class BookListView(generic.ListView):
    model = Book
    paginate_by = 5
    # context_object_name = 'book_list'
    # queryset = Book.objects.filter(title__icontains='zsolt')[:5]
   # 


class BookDetailView(generic.DetailView):
    model = Book
    # context_object_name = 'details'
    # template_name = 'catalog/book_detail.html'


class AuthorListView(generic.ListView):
    model = Author
    paginate_by = 5


class AuthorDetailView(generic.DetailView):
    model = Author

And finally here are the templates:

catalog/templates/base_generic.html:

<!DOCTYPE html>
<html lang="en">
<head>
  {% block title %}<title>Local Library</title>{% endblock %}
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
  <!-- Add additional CSS in static file -->
  {% load static %}
  <link rel="stylesheet" href="{% static 'css/styles.css' %}">
</head>
<body>
  <div class="container-fluid">
    <div class="row">
      <div class="col-sm-2">
      {% block sidebar %}
        <ul class="sidebar-nav">
          <li><a href="{% url 'index' %}">Home</a></li>
          <li><a href="{% url 'books' %}">All books</a></li>
          <li><a href="{% url 'authors' %}">All authors</a></li>
        </ul>
     {% endblock %}
      </div>
      <div class="col-sm-10 ">{% block content %}{% endblock %}
        {% block pagination %}
        {% if is_paginated %}
          <div class="pagination">
            <span class="page-links">
              {% if page_obj.has_previous %}
                <a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">previous</a>
              {% endif %}
              <span class="page-current">
                Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
              </span>
              {% if page_obj.has_next %}
                <a href="{{ request.path }}?page={{ page_obj.next_page_number }} ">next</a>
              {% endif %}
            </span>
          </div>
        {% endif %}
      {% endblock %}
      </div>
    </div>
  </div>
</body>
</html>

catalog/templates/catalog/book_details.html:

{% extends "base_generic.html" %}

{% block content %}
  <h1>Title: {{ book.title }}</h1>

  <p><strong>Author:</strong> <a href="{% url 'author-detail' book.author.pk %}">{{ book.author }}</a></p> <!-- author detail link not yet defined -->
  <p><strong>Summary:</strong> {{ book.summary }}</p>
  <p><strong>ISBN:</strong> {{ book.isbn }}</p> 
  <p><strong>Language:</strong> {{ book.language }}</p>  
  <p><strong>Genre:</strong> {{ book.genre.all|join:", " }}</p>   
 
  <div style="margin-left:20px;margin-top:20px">
    <h4>Copies</h4>

    {% for copy in book.bookinstance_set.all %}
      <hr>
      <p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{% else %}text-warning{% endif %}">
        {{ copy.get_status_display }}
      </p>
      {% if copy.status != 'a' %}
        <p><strong>Due to be returned:</strong> {{ copy.due_back }}</p>
      {% endif %}
      <p><strong>Imprint:</strong> {{ copy.imprint }}</p>
      <p class="text-muted"><strong>Id:</strong> {{ copy.id }}</p>
    {% endfor %}
  </div>
{% endblock %}

catalog/templates/catalog/book_list.html:

{% extends "base_generic.html" %}

{% block content %}
  <h1>Book List</h1>
  {% if book_list %}
  <ul>
    {% for book in book_list %}
      <li>
        <a href="{{ book.get_absolute_url }}">{{ book.title }}</a> ({{ book.author }}) {{ book.get_absolute_url }}
      </li>
    {% endfor %}
  </ul>
  {% else %}
    <p>There are no books in the library.</p>
  {% endif %}       
{% endblock %}

catalog/templates/catalog/author_list.html:

{% extends "base_generic.html" %}

{% block content %}

<h1>Author List</h1>

{% if author_list %}
  <ul>

  {% for author in author_list %}
    <li>
      <a href="{{ author.get_absolute_url }}">
      {{ author }} ({{author.date_of_birth}} - {% if author.date_of_death %}{{author.date_of_death}}{% endif %})
      </a>
    </li>
  {% endfor %}

 </ul>
{% else %}
  <p>There are no authors available.</p>
{% endif %}
        
        
        
{% endblock %}

catalog/templates/catalog/author_detail.html:

{% extends "base_generic.html" %}

{% block content %}
hello
{% endblock %}

The problem is that author_detail.html does not show up because django cannot reverse the 'author-detail' name. I know that the {{ author.get_absolute_url }} gives the right url back. I did everything in the same way for the Book model and thebook_list.htmlandbook_detail.html` works fine.

Could you please help me resolve the issue?

Answer

The error you're encountering, django.urls.exceptions.NoReverseMatch: Reverse for 'author-detail' with arguments '('',)' not found, suggests that the URL reverse lookup for the author detail page is being passed an empty or invalid primary key (''), which Django cannot resolve. Let's break down the issue and the possible fixes.

Issue Analysis

The line in your template book_details.html that is causing the issue is:

<a href="{% url 'author-detail' book.author.pk %}">{{ book.author }}</a>

Here, you're trying to generate a URL for the author's detail page, passing book.author.pk as an argument. However, if book.author.pk is empty or not set correctly, Django will attempt to reverse the URL with an empty value, which leads to the NoReverseMatch error.

Possible Causes & Fixes

  1. Check if book.author is None or missing:

    • The error might be happening because book.author is None or missing for some of the books in the database. When you try to access .pk on a None object, it will return an empty string.
    • You can add a check in the template to ensure that book.author exists before trying to generate the URL. Update your template like this:
    <p><strong>Author:</strong> {% if book.author %}
       <a href="{% url 'author-detail' book.author.pk %}">{{ book.author }}</a>
    {% else %}
       Unknown Author
    {% endif %}
    </p>
    

    This ensures that if book.author is None, it will display "Unknown Author" instead of attempting to generate a URL with an empty primary key.

  2. Ensure that every Book has an associated Author:

    • Check that all Book instances in your database have a valid Author associated with them. If any books are missing an author, this could lead to the issue you're seeing.
    • You can check for missing authors by running a query in your Django shell:
    from catalog.models import Book
    books_with_no_author = Book.objects.filter(author__isnull=True)
    

    If any books are returned from this query, you need to ensure that all Book instances have an associated Author.

  3. Fix the get_absolute_url method in Author model:

    • You've implemented get_absolute_url in the Author model correctly. Just to verify, ensure that the URL pattern name 'author-detail' exists and matches the one used in urls.py:
    path('author/<int:pk>', views.AuthorDetailView.as_view(), name='author-detail'),
    

    This path is correctly set up, so no changes are needed here. Just ensure the author-detail name matches everywhere it's used in templates.

Steps to Resolve

  • Step 1: Add the conditional check in the book_details.html template to handle missing authors.
  • Step 2: Verify that all Book objects have an associated Author in the database.
  • Step 3: Ensure the Author model's get_absolute_url method is correctly implemented (which it seems to be).

Once you've made these changes, the error should be resolved, and the author detail page should work as expected.