Django - 如何创建一个有效的 slug url?

Django - How to create a slug url that works?

我是新手,在尝试显示 post 的详细信息页面时遇到错误。我已经检查了与此问题相关的其他答案,但解决方案仍然不适合我。

这是我遇到的错误:

Reverse for 'blog_post' with no arguments not found. 1 pattern(s) tried: ['blog\/post/(?P<slug>[-\w]+)/$']

这是我的模型:

class Post(models.Model):
    STATUS_CHOICES = (
    ('draft', 'Draft'),
    ('published', 'Published'),
)

    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique_for_date='publish')
    author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=10, choices=STATUS_CHOICES, 
       default='draft')

   class Meta:
     ordering = ('-publish',)

   def __str__(self):
     return self.title

   def get_absolute_url(self):
      return reverse('blog:post', args=[str(self.slug)])

查看函数:

class BlogHomePageView(ListView):
  model = Post
  template_name = 'blog/index.html'

class PostDetailView(DetailView):
  model = Post
  template_name = 'blog/post.html'
  slug_url_kwarg = 'slug'
  query_pk_and_slug = True

网址模式:

path('', BlogHomePageView.as_view(), name='blog_home'),
re_path(r'post/(?P<slug>[-\w]+)/$', PostDetailView.as_view(), name='blog_post'),

base.html

<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
    <div class="container">
        <a class="navbar-brand" href="index.html">Toluwalemi</a>
        <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
                data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false"
                aria-label="Toggle navigation">
            Menu
            <i class="fas fa-bars"></i>
        </button>
        <div class="collapse navbar-collapse" id="navbarResponsive">
            <ul class="navbar-nav ml-auto">
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'blog_home' %}">Home</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'blog_about' %}">About</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'blog_post' %}">Sample Post</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{% url 'blog_contact' %}">Contact</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

详情页:

{% extends 'blog/base.html' %}

{% block title %}Post{% endblock %}


<!-- Page Header -->
{% block page_header %}
    <div class="post-heading">
        <h1>{{ post.title }}</h1>
        <h2 class="subheading">Problems look mighty small from 150 miles up</h2>
        <span class="meta">Posted by
              <a href="#">{{ post.author }}</a>
              on {{ post.publish }}</span>
    </div>
{% endblock %}

<!-- Post Content -->
<article>
    {% block content %}
        <p>{{ post.body }}</p>

列表页面:

{% extends 'blog/base.html' %}

{% block title %}Home{% endblock %}

<!-- Page Header -->
{% block page_header %}
    <div class="site-heading">
        <h1>Toluwalemi's Blog</h1>
        <span class="subheading">Official Blog</span>
    </div>
{% endblock %}

<!-- Main Content -->
{% block content %}
    {% for post in object_list %}
        <div class="post-preview">
            <a href="{{ post.get_absolute_url }}">
                <h2 class="post-title">
                    {{ post.title }}
                </h2>

如果您查看 URL 定义,您会发现它需要一个参数 slug:

re_path(r'post/(?P<slug>[-\w]+)/$', PostDetailView.as_view(), name='blog_post'),

顺便说一句,也可以表示为 Django 2.0:

path('post/<slug:slug>/', PostDetailView.as_view(), name='blog_post'),

现在,图像中的错误消息清楚地表明您正在调用没有所述参数的 URL 模板标签,它只有

href="{% url 'blog_post' %}"

并且没有 slug 参数。

您需要添加 slug 参数。

您甚至没有向我们展示您的问题中出现错误消息中显示的行的正确模板,因此我无法提供更多帮助。

伙计们,我终于明白了。我的 slug url 现在可以正常工作了。

错误实际上来自我的列表页面。详细视图的 url 写得不好。我没有包含名称空间。所以 <a href="{{ post.get_absolute_url }}"> 变成了 <a href="{% url 'blog:blog_post' post.slug %}"> 我还删除了模型和视图页面中的冗余代码行。

这是现在的样子。

models.py:

class Post(models.Model):
    STATUS_CHOICES = (
    ('draft', 'Draft'),
    ('published', 'Published'),
)

   title = models.CharField(max_length=200)
   slug = models.SlugField(max_length=200, default="")
   author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
   body = models.TextField()
   publish = models.DateTimeField(default=timezone.now)
   created = models.DateTimeField(auto_now_add=True)
   updated = models.DateTimeField(auto_now=True)
   status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')

   class Meta:
     ordering = ('-publish',)

   def __str__(self):
     return self.title

views.py

class BlogHomePageView(ListView):
   model = Post
   template_name = 'blog/index.html'
   context_object_name = 'posts'

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post.html'
    context_object_name = 'post'

blog/urls.py:

    urlpatterns = [
      path('', BlogHomePageView.as_view(), name='blog_home'),
      path('post/<slug:slug>/', PostDetailView.as_view(), name='blog_post'),
    ]

列表页面(index.html):

{% extends 'blog/base.html' %}

    {% block title %}Home{% endblock %}

    <!-- Page Header -->
    {% block page_header %}
        <div class="site-heading">
            <h1>Toluwalemi's Blog</h1>
            <span class="subheading">Official Blog</span>
        </div>
    {% endblock %}

    <!-- Main Content -->
    {% block content %}
        {% for post in posts %}
            <div class="post-preview">
                <a href="{% url 'blog:blog_post' post.slug %}">
                    <h2 class="post-title">
                        {{ post.title }}
                    </h2>