You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中自动为URL追加slug?

嘿,这个需求我太熟了!在Django里实现Stack Overflow那种「输入ID自动跳转到带slug的URL」的功能,其实分几步就能搞定,我给你拆解一下:

1. 先给模型配置自动生成的slug字段

首先你的模型得有slug字段,而且最好让它自动基于标题(或其他字段)生成,确保每个对象的slug唯一。比如以文章模型为例:

from django.db import models
from django.utils.text import slugify

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True, blank=True)
    # 其他业务字段,比如内容、发布时间等

    def save(self, *args, **kwargs):
        # 如果slug为空,就基于标题自动生成
        if not self.slug:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)

这里要注意slug字段设置unique=True,避免不同对象出现重复slug的情况。

2. 配置URL路由(两种方案可选)

方案一:拆分两个路由(更直观)

一个路由处理带slug的完整URL,另一个处理仅带ID的URL,后者负责重定向:

from django.urls import path
from . import views

urlpatterns = [
    # 完整的带slug的URL,对应详情页
    path('posts/<int:pk>/<slug:slug>/', views.post_detail, name='post-detail'),
    # 仅带ID的URL,负责重定向到完整URL
    path('posts/<int:pk>/', views.post_detail_redirect, name='post-detail-redirect'),
]

方案二:单路由匹配两种情况(更简洁)

用正则路由匹配「带ID」和「ID+slug」两种格式,这样不用写两个路由:

from django.urls import re_path
from . import views

urlpatterns = [
    re_path(r'^posts/(?P<pk>\d+)(?:/(?P<slug>[-\w]+))?/$', views.post_detail, name='post-detail'),
]

这里的(?:/(?P<slug>[-\w]+))?是可选分组,意思是slug部分可有可无。

3. 在视图里处理重定向逻辑

核心逻辑就是:如果用户访问的URL没有slug,或者slug和对象实际的slug不匹配,就自动重定向到正确的带slug的URL。

from django.shortcuts import get_object_or_404, redirect, render
from .models import Post

def post_detail(request, pk, slug=None):
    # 根据ID获取对象
    post = get_object_or_404(Post, pk=pk)
    
    # 检查slug是否正确:要么没传slug,要么传的slug和实际不符
    if slug != post.slug:
        # 永久重定向(permanent=True),对SEO友好,浏览器会缓存这个重定向规则
        return redirect('post-detail', pk=post.pk, slug=post.slug, permanent=True)
    
    # slug正确,正常渲染详情页
    return render(request, 'posts/post_detail.html', {'post': post})

如果用的是方案一的拆分路由,那重定向视图可以简化成:

def post_detail_redirect(request, pk):
    post = get_object_or_404(Post, pk=pk)
    return redirect('post-detail', pk=pk, slug=post.slug, permanent=True)

最后补充个小细节

记得在模板里生成URL的时候,始终使用带slug的完整URL(比如{% url 'post-detail' pk=post.pk slug=post.slug %}),这样用户平时点击的都是标准URL,只有手动输入ID的时候才会触发重定向。

内容的提问来源于stack exchange,提问作者Justin Paul Obsines

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:42:03