NoMatchReverse 错误 ListView to DetailView 似乎无法传递 url 参数

NoMatchReverse error ListView to DetailView can't seem to pass url parameters

我已经为这个问题苦苦挣扎了一天多了。当涉及到 NoReverseMatch 错误时,我真的不明白要寻找什么。每次我提供错误的答案时,我都会收到一个我不知道如何处理的新错误。非常感谢您帮助我理解如何调试此问题,因为我现在不知所措。

我正在构建一个包含两个应用程序的网站。 1. 主网站和 2. 博客。我最近创建了博客应用程序并连接了 url,这样您就可以从主页转到博客主页(一个列表视图),然后我要做的就是让用户可以点击文章的标题他们感兴趣,它将显示与文章相关的文本和其他信息。问题是我不断在博客主页或博客详细信息视图页面上收到 NoReverseMatch 错误,我什至不知道从哪里开始进行故障排除。我是 OOP、Django 和 python 的新手,所以这一切都让人迷失方向。

我最近遇到的错误是

NoReverseMatch at /blog/
Reverse for 'blog_post_detail' with keyword arguments '{'title': 'Another One'}' not found. 1 pattern(s) tried: ['blog/articles/(?P<title>[\.\w-]+)/$']

主要urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/login/', admin.site.urls),
    path('blog/', include(('blog.urls', 'blog'), namespace='blog')),
    path('', include(('website.urls', 'main'), namespace='main')),
]

博客urls.py:

from django.urls import path, re_path, reverse

from .views import BlogHomeView, BlogDetailView

app_name= 'blog'

urlpatterns = [
    re_path(r'^articles/(?P<title>[\.\w-]+)/$', BlogDetailView.as_view(), name='blog_post_detail'),
    re_path(r'^$', BlogHomeView.as_view(), name='blog_home'),

    ]

博客views.py

from django.shortcuts import render
from django.views.generic.base import TemplateView
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from django.core.paginator import Paginator
from django.shortcuts import render
from django.views import View
from django.http import HttpResponse
from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import ArticlePosts, ArticleCategories
from django.urls import reverse_lazy


# Create your views here.


class BlogHomeView(ListView):
    template_name = 'blog/blog_home.html'
    model = ArticlePosts
    context_object_name = "blog_articles"

class BlogDetailView(DetailView):
    template_name = 'blog/blog_post_detail.html'
    model = ArticlePosts

models.py:

from django.db import models
from django.utils import timezone 
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify
from pathlib import Path
from django.conf import settings
from django.urls import reverse


class ArticleCategories(models.Model):
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated at")
    title = models.CharField(max_length=255, verbose_name="Title")

    class Meta:
        verbose_name = "Category"
        verbose_name_plural = "Categories"
        ordering = ['title']

    def __str__(self):
        return self.title

class ArticlePosts(models.Model):
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created at")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated at")
    is_published = models.BooleanField(default=False, verbose_name="Is published?")
    published_at = models.DateTimeField(null=True, blank=True, editable=False, verbose_name="Published at")
    category = models.ForeignKey(ArticleCategories, verbose_name="Category", on_delete=models.CASCADE)
    author = models.ForeignKey('auth.User', verbose_name="Author", on_delete=models.CASCADE)
    title = models.CharField(max_length=200, verbose_name="Title")
    description = models.CharField(max_length=500, verbose_name="Description", default="All content is created by our founders.")
    text = models.TextField(verbose_name="Text")
    image = models.ImageField(upload_to='photos', default="static/static/img/default.jpg")
    fig_caption = models.TextField(default="Default Image", verbose_name="Caption")
    def slug(self):
        return slugify(self.title)


    class Meta:
        verbose_name = "Post"
        verbose_name_plural = "Posts"
        ordering = ['-created_at']

    def publish(self):
        self.is_published = True
        self.published_at = timezone.now()
        self.save()

    def get_absolute_url(self):
        return reverse('blog:blog_post_detail', kwargs={'title': self.title})

    def __str__(self):
        return self.title

blog_home.html:

<img src="{% static 'static/img/ssg600.png' %}" alt="About us" class="img-responsive img-thumbnail pull-right m-l m-b" width=150px height=150px> -->
            {% for post in blog_articles %}
            <div class="block block-border-bottom-grey block-pd-sm">
            <h3 class="block-title" id="nursing">
                <a href="{{ post.get_absolute_url }}"><b>{{ post.title }}</b></a>
              </h3>
            <img src="{{ post.image.url }}" alt="Services" class="img-responsive img-thumbnail pull-left m-l m-b" width=150px height=150px>
            {{ post.description|linebreaks }}
          </div>
          {% endfor %}

base.html:

<li><a href="{% url 'blog:blog_home' %}" tabindex="-1" class="menu-item">Check Out our Blog</a></li>


Before I posted this I had had get_absolute_url set to this:

def get_absolute_url(自我): return反向('blog:blog_post_detail',kwargs={'slug':slugify(self.title)})

But it gave me a slugfield error. So I switched it to title, and now I have this error:

NoReverseMatch 在 /blog/ 反向 'blog_post_detail' 关键字参数 '{'title': 'Another One'}' 未找到。尝试了 1 种模式:['blog/articles/(?P[\.\w-]+)/$']


I would really appreciate any help on this.

几件事:

  • Django 惯例是以单数形式命名 类: ArticleCategoryArticlePost
  • 不应将 slug() 定义为方法,而应定义 slug 字段并在 save() override
  • 中设置值
  • <title> 在 url 中需要一个 slug,所以你应该传递 self.slug(在你创建 slug 字段之后)

那么这个:

def get_absolute_url(self):
    return reverse('blog:blog_post_detail', kwargs={'title': self.title})

将更改为:

def get_absolute_url(self):
    return reverse('blog:blog_post_detail', kwargs={'title': self.slug})

但是,我不会定义 get_absolute_url(),而是像这样渲染模板(确保在模板文件的顶部包含 {% load static %}):

<h3 class="block-title" id="nursing">
    <a href="{% url 'blog_post_detail' post.slug %}"><b>{{ post.title }}</b></a>
</h3>