使用get_absolute_url触发NoReverseMatch错误,请求排查问题
Django中get_absolute_url触发NoReverseMatch错误的排查与解决
错误信息
NoReverseMatch at /mega_archive/books/ Reverse for 'book' with arguments '('',)' not found. 1 pattern(s) tried: ['mega_archive/book/(?P<book>[-a-zA-Z0-9_]+)/\Z']
问题根源
错误核心是:调用reverse生成book路由时传入了空字符串参数,而你的URL规则mega_archive/book/<slug:book>/要求参数必须匹配非空的slug格式([-a-zA-Z0-9_]+),空字符串不符合规则导致匹配失败。
本质原因是数据库中存在slug字段为空的Book实例,模板循环调用book.get_absolute_url()时,空slug被传入reverse触发错误。
你的代码参考
views.py
def books(request): books = Book.objects.all() return render(request, 'mega_archive/books.html',{ 'books':books }) def book(request, book): book = get_object_or_404(Book, slug=book) return render(request, 'mega_archive/book_details.html', { 'book':book })
urls.py
path('books/', views.books, name='books'), path('book/<slug:book>/', views.book, name='book'),
models.py
def get_absolute_url(self): return reverse('mega_archive:book', args=[self.slug]) def __str__(self): return self.title
模板代码
{% for book in books %} <a href="{{book.get_absolute_url}}">{{book}}</a><br> {% endfor %}
解决步骤
修复现有空slug数据
进入Django Shell,批量更新所有空slug的书籍记录:from django.utils.text import slugify from mega_archive.models import Book # 用标题生成slug,处理重复情况 for book in Book.objects.filter(slug__exact=''): base_slug = slugify(book.title) current_slug = base_slug counter = 1 while Book.objects.filter(slug=current_slug).exists(): current_slug = f"{base_slug}-{counter}" counter += 1 book.slug = current_slug book.save()自动生成slug,避免后续空值
修改Book模型,在保存时自动生成唯一slug:from django.db import models from django.utils.text import slugify class Book(models.Model): title = models.CharField(max_length=200) slug = models.SlugField(unique=True, blank=True) def save(self, *args, **kwargs): if not self.slug: base_slug = slugify(self.title) current_slug = base_slug counter = 1 while Book.objects.filter(slug=current_slug).exists(): current_slug = f"{base_slug}-{counter}" counter += 1 self.slug = current_slug super().save(*args, **kwargs) def get_absolute_url(self): return reverse('mega_archive:book', args=[self.slug]) def __str__(self): return self.title验证URL命名空间
确保项目根urls.py中正确配置了命名空间:from django.urls import path, include urlpatterns = [ # 其他路由... path('mega_archive/', include('mega_archive.urls', namespace='mega_archive')), ]
内容的提问来源于stack exchange,提问作者Arnold Schwartzkopf
相关产品推荐
相关产品推荐

