如何在Django中配置基于slug的路由

430 阅读3分钟

我们的Post模型有一个slug字段,我们之前已经设置好了。现在我们想在Django中配置基于slug的路由。为了设计一个应用程序的URL,我们学习了如何使用Python模块URLconf或URL配置。URLconfg使用Python代码在URL路径表达式和视图中定义的Python函数之间进行映射。一些路由路径是静态的,而一些是动态的。换句话说,我们可以使用URL中的变量数据来确定如何映射到一个特定的视图函数。我们已经看到了如何使用基于整数的ID路由,在本教程中,我们将看到如何改用基于字符串的蛞蝓。


蛞蝓定义

Post mdel使用*lug = models.SlugField()*定义了lug,下面是突出显示。我们的系统目前在数据库中有三个Post模型,每个模型都有一个slug与之相关。到目前为止,我们的弹头是 a-new-title, second-post,以及 third-post.
posts/models.py

from django.db import models


# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField()
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

    def snippet(self):
        return self.body[0:70]

为Slug捕获定义URL路径

Web应用程序响应Http请求并使用请求中的参数来决定如何路由。我们的目标是能够访问像http://localhost:8000/posts/a-new-title/, http://localhost:8000/posts/second-post/, and http://localhost:8000/posts/third-post/ 这样的链接,Django将路由到每个特定的Post细节视图。为了捕捉URL中的slug变量,我们可以在**path()**函数中使用slug:slug参数。这在下面的代码中得到了强调。

posts/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.post_list),
    path('<slug:slug>/', views.post_detail, name='post_detail'),
]

在上面的代码中,需要注意的另一件重要事情是 **name**参数被设置为post_detail。这是一个命名的URL模式,或一个命名的路由。这使你有能力链接到名称,而不是硬编码的hrefs。我们稍后会看到它是如何工作的。


使用捕获的Slug

现在在views.py文件的post_detail()函数中,我们可以使用*post_detail(request, slug)接受从URL中捕获的slug。然后,我们使用Django ORMPost.objects.get(slug=slug)*代码,用这个lug来查询数据库。最后,我们渲染post_detail.html模板,同时将持有查询结果的上下文变量传递给数据库。

posts/views.py

from django.shortcuts import render
from .models import Post


def post_list(request):
    posts = Post.objects.all().order_by('date')
    return render(request, 'posts/post_list.html', {'posts': posts})


def post_detail(request, slug):
    post = Post.objects.get(slug=slug)
    return render(request, 'posts/post_detail.html', {'post': post})

通过Slug进行链接

帖子列表页需要每个帖子通过slug链接到帖子详情页。我们在href属性中使用*{% url 'post_detail' post.slug %}*来指定。这段代码在这里被强调了。

post/templates/posts/post_list.html

{% extends "./layout/base.html" %}
{% load static %}

{% block content %}
    {% for post in posts %}
        <div class="card mb-4" style="width: 40rem">
            <img src="{% static 'posts/images/'|add:post.slug|add:'.jpeg' %}" class="card-img-top">
            <div class="card-body">
                <h3 class="card-title">{{ post.title }}</h3>
                <h6 class="card-subtitle mb-2 text-muted">{{ post.slug }}</h6>
                <p class="card-text">{{ post.snippet }}...</p>
                <a href="{% url 'post_detail' post.slug %}" class="btn btn-primary">Read More</a>
            </div>
        </div>
    {% endfor %}
{% endblock content %}

现在我们有了使用slug的链接,就像我们在这里看到的那样。

django link via slug


使用帖子细节模板

所有的管道都已就位,现在我们要做的是提供一个post_detail.html模板,像这样。

posts/templates/posts/post_detail.html

{% extends "./layout/base.html" %}
{% load static %}

{% block content %}

    <div class="card mb-4" style="width: 40rem">
        <img src="{% static 'posts/images/'|add:post.slug|add:'.jpeg' %}" class="card-img-top">
        <div class="card-body">
            <h3 class="card-title">{{ post.title }}</h3>
            <h6 class="card-subtitle mb-2 text-muted">{{ post.slug }}</h6>
            <p class="card-text">{{ post.body }}</p>
        </div>
    </div>

{% endblock content %}

slug example one

djanglo slug two

django slug three

Django中基于Slug的路由总结

为了使Django中的URL漂亮,我们可以使用基于lug的路由。使用蛞蝓还能带来SEO方面的好处,因为搜索引擎对描述性蛞蝓的理解要比URL中的简单ID更好。在本教程中,我们学习了如何处理使用slug进行路由,查询数据库,以及渲染一个帖子详情页的模板。