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

Django站点修改slug后旧URL自动重定向解决方案

Django站点Slug修改后的自动重定向方案

当你修改站点内容的slug导致旧URL失效时,不用逐个编写重定向规则,下面是两种自动处理的实用方案:

方案一:模型存储历史Slug+视图自动匹配重定向

这种方案适合单个或少数模型的场景,核心思路是把每个内容的旧slug都存在模型里,访问时自动匹配并跳转。

  1. 修改模型,添加历史slug字段
    给需要处理的模型(比如文章、产品模型)新增一个字段保存所有用过的旧slug,推荐用JSON数组存储:
from django.db import models
from django.contrib.postgres.fields import JSONField  # PostgreSQL用户直接用,其他数据库可换TextField存JSON字符串

class Article(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    old_slugs = JSONField(default=list)  # 存储历史slug列表
    # 其他业务字段...
  1. 用信号自动记录旧slug
    添加pre_save信号,当slug被修改时,自动把旧slug追加到历史列表:
from django.db.models.signals import pre_save
from django.dispatch import receiver

@receiver(pre_save, sender=Article)
def track_old_slugs(sender, instance, **kwargs):
    if instance.pk:
        original = sender.objects.get(pk=instance.pk)
        if original.slug != instance.slug and original.slug not in instance.old_slugs:
            instance.old_slugs.append(original.slug)
  1. 修改视图,处理旧slug跳转
    在详情视图里,先尝试用当前slug查找内容,找不到则匹配历史slug,找到后返回301永久重定向:
from django.shortcuts import get_object_or_404, redirect
from django.views.generic import DetailView

class ArticleDetailView(DetailView):
    model = Article
    slug_field = 'slug'
    slug_url_kwarg = 'slug'

    def get_object(self, queryset=None):
        try:
            return super().get_object(queryset)
        except self.model.DoesNotExist:
            # 尝试匹配旧slug
            target_obj = get_object_or_404(self.model, old_slugs__contains=self.kwargs['slug'])
            # 301重定向告诉搜索引擎更新索引
            return redirect(target_obj.get_absolute_url(), permanent=True)

方案二:全局中间件处理所有404中的旧Slug

如果多个模型都有slug修改需求,可以写一个全局中间件,自动拦截404请求并尝试匹配旧slug:

  1. 编写中间件
    在你的app下创建middleware.py文件:
from django.http import HttpResponsePermanentRedirect
from django.urls import resolve

class OldSlugRedirectMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        # 只处理404状态的请求
        if response.status_code == 404:
            try:
                match = resolve(request.path_info)
                # 针对需要处理的视图(替换成你的详情页视图名称)
                if match.view_name in ['article_detail', 'product_detail']:
                    slug = match.kwargs.get('slug')
                    if slug:
                        # 根据视图名称对应不同模型
                        if match.view_name == 'article_detail':
                            from .models import Article
                            obj = Article.objects.get(old_slugs__contains=slug)
                        elif match.view_name == 'product_detail':
                            from .models import Product
                            obj = Product.objects.get(old_slugs__contains=slug)
                        return HttpResponsePermanentRedirect(obj.get_absolute_url())
            except (resolve.Resolver404, Exception):
                # 匹配失败,返回原404
                pass
        return response
  1. 注册中间件
    在项目settings.py的MIDDLEWARE列表中添加该中间件:
MIDDLEWARE = [
    # 其他中间件...
    'your_app_name.middleware.OldSlugRedirectMiddleware',
]

关键注意点

  • 必须使用301永久重定向,这样搜索引擎会更新索引,逐步替换旧URL,避免后续用户通过搜索进入错误页面。
  • 若使用MySQL,可将JSONField换成TextField,存储时转成JSON字符串,查询时用old_slugs__contains=f'"{slug}"'实现精确匹配,避免误匹配。
  • 已被谷歌收录的旧URL,通过这种方式会自动跳转,无需手动维护大量重定向规则。

内容的提问来源于stack exchange,提问作者PolarBear

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:11:27