You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Django 3如何将详情页URL从ID形式改为ID+标题形式

没问题,我来帮你把详情页URL改成包含标题的SEO友好形式,咱们一步步来操作:

步骤1:给模型添加Slug字段

首先需要在你的Deneme1Model里添加一个slug字段,用来存储标题的URL友好版本(比如把“Bu Konu Başlığı”转换成“bu-konu-basligi”)。修改models.py

from django.db import models
from django.utils import timezone
from django.utils.text import slugify  # 导入slugify工具

class Deneme1Model(models.Model):
    baslik = models.CharField(max_length=50, verbose_name='BAŞLIK')
    aKaydi = models.CharField(max_length=50, verbose_name='A KAYDI')
    dosyaYukle = models.FileField(upload_to='media', verbose_name='DOSYA YÜKLE')
    yuklemeTarihi = models.DateTimeField(default=timezone.now)
    yayinKontrol = models.BooleanField(default=True)
    slug = models.SlugField(max_length=255, blank=True, verbose_name='URL BAŞLIĞI')  # 新增slug字段

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

    def __str__(self):
        return self.baslik
步骤2:更新视图函数

现在URL里会包含pkslug两个参数,所以需要修改detay视图的参数,同时把查询逻辑改成更高效的单个对象查询(原来的filter返回的是QuerySet,用get_object_or_404更合适,没找到对象会自动返回404页面):

from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from .models import *

def index(request):
    girdiler = Deneme1Model.objects.filter(yuklemeTarihi__lte=timezone.now()).order_by('-yuklemeTarihi')
    context ={
        'girdiler':girdiler
    }
    return render(request, 'deneme1Uygulama/index.html', context)

def ekle(request):
    return render(request, 'deneme1Uygulama/ekle.html')

def detay(request, pk, slug):  # 新增slug参数
    girdi = get_object_or_404(Deneme1Model, pk=pk)  # 获取单个对象
    context ={
        'girdi': girdi  # 传递单个对象到模板
    }
    return render(request, 'deneme1Uygulama/detay.html', context)

def sayfaYok(request):
    return render(request, 'deneme1Uygulama/404.html')
步骤3:修改URL配置

更新urls.py里的详情页路径,添加slug参数:

from django.urls import path
from .import views
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('', views.index, name='index'),
    path('ekle/', views.ekle, name='ekle'),
    path('detay/<int:pk>/<slug:slug>/', views.detay, name='detay'),  # 修改这里,添加slug部分
    path('404/', views.sayfaYok, name='sayfaYok'),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
步骤4:更新模板中的URL链接

现在需要修改detay.html里的URL生成逻辑,同时因为视图现在传递的是单个对象,所以可以去掉循环(原来的循环是多余的,因为一个pk对应一个对象):

{% block content %}
<div class="row">
    <div class="col-12 d-flex justify-content-center">
        <div class="card w-100">
            <img class="card-img-top img-fluid umaxhe20" src="{{ girdi.dosyaYukle.url }}" alt="Card image cap">
            <div class="card-body">
                <h5 class="card-title">{{ girdi.baslik }}</h5>
                <p class="card-text">{{ girdi.aKaydi }}</p>
                <a href="{% url 'detay' girdi.pk girdi.slug %}" class="btn btn-primary">{{ girdi.yuklemeTarihi }}</a>
            </div>
        </div>
    </div>
</div>
{% endblock content %}

注意:如果你的index.html里也有指向详情页的链接,记得同样修改成{% url 'detay' girdi.pk girdi.slug %}

步骤5:处理现有数据的Slug

因为我们新增了slug字段,需要先执行数据迁移,然后给已有的数据生成slug:

  1. 生成迁移文件:
python manage.py makemigrations
  1. 执行迁移:
python manage.py migrate
  1. 给现有数据批量生成slug:
    打开Django Shell:
python manage.py shell

然后执行以下代码:

from deneme1Uygulama.models import Deneme1Model
from django.utils.text import slugify

for girdi in Deneme1Model.objects.all():
    if not girdi.slug:
        girdi.slug = slugify(girdi.baslik)
        girdi.save()

完成这些步骤后,你的详情页URL就会变成http://localhost:8000/detay/1/bu-konu-basligi这样的形式啦!而且即使标题修改了,只要pk不变,旧的URL依然能访问(因为视图只靠pk查询),不会影响SEO。

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

火山引擎 最新活动