Django动态生成域名后URL:页面渲染及404处理是否合理?
问题背景
我正在搭建一个博客网站,为每篇文章设置了唯一标题,希望文章的URL格式为domain_name/<article_title>/。
现有两个模型:
class A(models.Model): title = models.CharField(max_length=500,unique=True) class B(models.Model): title = models.CharField(max_length=500,unique=True)
app.urls.py配置:
urlpatterns = [ path('',view.index,name="index"), path('contact/', contact, name="contact"), path('about/', about, name="about"), path('terms-and-conditions/', terms, name="terms_and_conditions"), path('privacy/', privacy, name="privacy"), path('<str:title>/', article_details, name="article_details"), ]
视图函数代码:
def article_details(request,title): if 'title_in_model_A': render 'some_page_A' if 'title_in_model_B: render 'some_page_B' render(request,'app/404.html')
project.urls配置:
urlpatterns = [ path('admin/', admin.site.urls), path('', include('app.urls')), ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) handler404 = 'app.views.view_404'
咨询两个问题:
- 这种页面渲染方式是否合理?
- 404请求是否处理正确?
问题1:页面渲染方式是否合理?
这种方式完全不合理,核心问题如下:
- 判断逻辑完全失效:代码里的
if 'title_in_model_A'是判断字符串非空,永远为True,会直接执行第一个render,后面的代码根本不会执行;第二个判断还存在语法错误(缺少闭合引号)。 - 未实际查询数据库:当前代码没有去模型A、B中校验是否存在对应title的记录,只是写了假的判断条件,完全达不到区分不同模型文章的目的。
- 可维护性极差:如果后续新增模型C、D,必须不断在视图里追加判断分支,不符合代码开闭原则。
- URL参数风险:直接用title作为URL参数,若标题包含空格、特殊字符,会导致URL不规范,容易出现编码问题。
正确的实现思路
- 实际查询数据库,通过异常捕获判断记录是否存在:
from django.http import Http404 def article_details(request, title): try: obj = A.objects.get(title=title) return render(request, 'some_page_A.html', {'obj': obj}) except A.DoesNotExist: try: obj = B.objects.get(title=title) return render(request, 'some_page_B.html', {'obj': obj}) except B.DoesNotExist: raise Http404("文章不存在")
- 建议改用
SlugField替代直接用title作为URL参数:给模型添加slug = models.SlugField(unique=True),生成符合URL规范的字符串(比如将My First Article转为my-first-article),URL配置改为path('<slug:slug>/', article_details, name="article_details"),避免特殊字符问题。 - 若后续模型较多,可抽象基类或使用通用视图,减少重复代码。
问题2:404请求是否处理正确?
当前处理方式不正确,问题点:
- 状态码错误:直接
render(request,'app/404.html')返回的是200 OK状态码,浏览器会认为这是正常响应,不利于SEO和客户端错误判断。 - 未触发全局handler404:视图里的手动render不会调用配置的
handler404视图,全局404配置形同虚设。 - 逻辑走不到404分支:第一个判断永远为True,代码根本不会执行到最后一行的404渲染。
正确的处理方式
- 查询不到记录时抛出
Http404异常,让Django自动调用全局配置的handler404:
from django.http import Http404 def article_details(request, title): # ...查询逻辑 except B.DoesNotExist: raise Http404("文章不存在")
- 确保自定义的
view_404视图返回正确的404状态码:
def view_404(request, exception): return render(request, 'app/404.html', status=404)
内容的提问来源于stack exchange,提问作者Manoj Kamble
相关产品推荐
相关产品推荐

