当前位置: 首页 > news >正文

Django 视图与路由基础:从URL映射到视图函数

        在 Django 开发中,“URL路由”和“视图”是处理用户请求的核心环节 —— 路由负责将用户输入的 URL 映射到对应的处理逻辑,视图则负责执行逻辑、交互数据并返回响应。它们共同构成了 “请求 - 处理 - 响应” 流程的骨架,也就是连接前端页面与后端模型的关键桥梁。本文将从基础入手,带你掌握 URL 路由的配置技巧和视图函数的核心写法,搭建起 Django 处理请求的基础能力

一、URL 路由配置

        URL路由的本质是“URL 路径” 与 “视图函数” 的映射关系。当用户发送 HTTP 请求(如访问http://127.0.0.1:8000/article/1/)时,Django 会通过路由配置找到对应的视图函数,执行后返回响应

1、路由基础

        Django 的路由配置写在 urls.py 文件中,核心是 urlpatterns 列表——每个path()函数定义一条路由规则,包含URL路径、“视图函数”、“路由名称”三个关键要素

示例:基础路由配置

# 项目主 urls.py(或应用的 urls.py)
from django.contrib import admin
from django.urls import path
from myapp import views  # 导入应用的视图函数urlpatterns = [# 管理员后台路由(Django自带)path('admin/', admin.site.urls),# 首页路由:访问 / 时,调用 views.index 视图,命名为 'home'path('', views.index, name='home'),# 文章详情路由:访问 /article/1/ 时,调用 views.article_detail,命名为 'article_detail'path('article/<int:pk>/', views.article_detail, name='article_detail'),# 分类文章列表路由:访问 /category/tech/ 时,调用 views.category_articles,命名为 'category_articles'path('category/<slug:slug>/', views.category_articles, name='category_articles'),
]

注解:path(router,view,name=None)

router: URL路径规则,支持参数的捕获        view:对应的视图函数,请求会传递给改函数

name: 路由的唯一名称,用于“反向解析”

2、Django 处理请求的完整流程

当用户发送一个HTTP请求(如http://127.0.0.1:8000/article/1/),Django会按一下步骤处理:

①接收请求:服务器接收用户的 HTTP 请求,提取 URL 路径(如 /article/1/ )

②解析URL:忽略域名(127.0.0.1:8000)、查询参数和锚点,仅保留路径部分

③匹配路由:遍历 urlpatterns 列表,找到与路径匹配的 path 规则(如<int:pk>匹配1)

④调用视图:将请求对象(request)和捕获的参数(如pk=1)传递给对应的视图函数

⑤返回响应:视图函数处理完成后,返回 HttpResponse 对象,Django 将其转换为 HTTP响应发送给用户

3、路径转换器:捕获 URL 中的参数

当需要从 URL 中提取参数(如文章 ID、分类别名)时,Django 提供了路径转换器,无需手动解析字符串。常用转换器如下:

转换器描述适用场景示例
str匹配除斜杠(/)外的任意字符字符串参数(如标题、别名)path('user/<str:username>/', views.user_profile)
int匹配非负整数主键 ID、页码path('article/<int:pk>/', views.article_detail)
slug匹配字母、数字、下划线、连字符(URL 友好字符串)分类别名、文章短标题path('category/<slug:slug>/', views.category_articles)
uuid匹配 UUID 字符串(唯一标识)安全的唯一 ID(如订单号)path('order/<uuid:order_id>/', views.order_detail)
path匹配包含斜杠的完整路径文件路径path('file/<path:file_path>/', views.file_view)

示例:用路径转换器实现文章详情与分类列表

# myapp/urls.py(应用的路由配置)
from django.urls import path
from . import viewsurlpatterns = [# 文章详情:捕获整数类型的pk(主键)path('article/<int:pk>/', views.article_detail, name='article_detail'),# 分类列表:捕获slug类型的分类别名path('category/<slug:slug>/', views.category_articles, name='category_articles'),
]# myapp/views.py(对应的视图函数)
from django.shortcuts import render, get_object_or_404
from .models import Article, Categorydef article_detail(request, pk):"""根据pk获取文章详情,不存在则返回404"""# get_object_or_404:找不到对象时自动抛出404错误article = get_object_or_404(Article, pk=pk)return render(request, 'article_detail.html', {'article': article})def category_articles(request, slug):"""根据slug获取分类下的文章列表"""category = get_object_or_404(Category, slug=slug)# 关联查询:获取该分类下的所有文章articles = Article.objects.filter(category=category)return render(request, 'category_articles.html', {'category': category, 'articles': articles})

模版渲染示例(article_detail.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>{{ article.title }}</title>
</head>
<body><h1>{{ article.title }}</h1><p>{{ article.content }}</p><p>发布时间:{{ article.created_at|date:"Y-m-d" }}</p>
</body>
</html>

4、正则表达式:处理复杂 URL 模式

当路径规则需要更灵活的匹配(如 “按年月归档文章”/article/2025/09/),路径转换器无法满足时,可使用正则表达式配置路由,需用re_path()函数

示例:用正则实现文章年月归档

# myapp/urls.py
from django.urls import path, re_path  # 导入re_path
from . import viewsurlpatterns = [# 匹配格式:/article/2025/09/(4位年份+2位月份)# (?P<year>[0-9]{4}):命名分组,捕获4位数字作为year参数# (?P<month>[0-9]{2}):捕获2位数字作为month参数re_path(r'^article/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.article_archive, name='article_archive'),
]# myapp/views.py
def article_archive(request, year, month):"""获取指定年月的文章列表"""# 过滤条件:created_at的年份=year,月份=montharticles = Article.objects.filter(created_at__year=year,created_at__month=month)return render(request, 'article_archive.html', {'year': year,'month': month,'articles': articles})

模版渲染示例

<h1>{{ year }}年{{ month }}月文章归档</h1>
{% if articles %}<ul>{% for article in articles %}<li><a href="{% url 'article_detail' article.pk %}">{{ article.title }}</a><span>发布于:{{ article.created_at|date:"Y-m-d H:i" }}</span></li>{% endfor %}</ul>
{% else %}<p>该月份暂无文章</p>
{% endif %}

5、路由进阶技巧

(1)URLconf 的查找规则

Django 的URLconf 仅匹配URL的路径部分,忽略一下内容

①域名        ②查询参数:如/article/1/?page=2中的?page=2不参与匹配

③锚点:如/article/1/#comment中的#comment不参与匹配

此外,RLconf 不区分 HTTP 方法 —— 同一 URL 的 GET、POST 请求会映射到同一个视图函数,需在视图中通过 request.method 判断

(2)指定视图参数的默认值

可在路由中为视图参数设置默认值,避免重复配置路由。例如 “文章列表分页”,默认显示第 1 页:

# myapp/urls.py
urlpatterns = [# 默认分页:/articles/page/ → 对应page=1path('articles/page/', views.article_list, name='article_list_default'),# 指定分页:/articles/page/2/ → 对应page=2path('articles/page/<int:page>/', views.article_list, name='article_list_paginated'),
]# myapp/views.py
def article_list(request, page=1):  # page默认值为1"""文章列表分页视图"""# 分页逻辑(后续会讲,此处简化)return render(request, 'article_list.html', {'page': page})

(3)包含其他 URLconf:拆分大型项目路由

大型项目中,多个应用(如blog、api、user)的路由混在一起会难以维护。可将每个应用的路由拆到各自的urls.py,再通过include()导入主路由

示例:

# 项目主 urls.py
from django.contrib import admin
from django.urls import path, include  # 导入includeurlpatterns = [path('admin/', admin.site.urls),# 将 /blog/ 开头的URL交给 blog 应用的 urls.py 处理path('blog/', include('blog.urls', namespace='blog')),# 将 /api/ 开头的URL交给 api 应用的 urls.py 处理path('api/', include('api.urls', namespace='api')),
]# blog/urls.py(blog应用的路由)
from django.urls import path
from . import viewsapp_name = 'blog'  # 应用命名空间(配合namespace使用)
urlpatterns = [path('', views.blog_home, name='blog_home'),  # 匹配 /blog/path('article/<int:pk>/', views.article_detail, name='article_detail'),  # 匹配 /blog/article/1/
]

(4)反向解析:避免硬编码 URL

硬编码 URL(如<a href="/blog/article/1/">)会导致后续修改路径时需全局替换,效率低下。通过 “路由名称” 反向生成 URL(即 “反向解析”),可解决此问题

反向解析的两种场景:①在视图中使用:通过reverse()函数,传入路由名称和参数;

在模板中使用:通过{% url '路由名称' 参数 %}模板标签

示例:

# 1. 视图中反向解析(myapp/views.py)
from django.urls import reverse
from django.shortcuts import redirectdef redirect_to_article(request, pk):"""重定向到文章详情页"""# 反向生成URL:根据名称'article_detail'和pk=pk生成 /blog/article/pk/article_url = reverse('blog:article_detail', args=[pk])  # args传递位置参数return redirect(article_url)  # 重定向到生成的URL# 2. 模板中反向解析(article_list.html)
{% for article in articles %}<!-- 生成 /blog/article/文章pk/ 的链接 --><a href="{% url 'blog:article_detail' article.pk %}">{{ article.title }}</a>
{% endfor %}

(5)命名空间:解决多应用同名路由冲突

当多个应用存在同名路由是(如 blog 和 user 都有 name='index' 的路由),反向解析会无法区分,此时需要通过“命名空间”(namespace)隔离

配置步骤:

主路由设置 namespace:include() 时指定 namespace

应用路由设置 app_name:在应用的 urls.py 中定义 app_name

示例:

# 项目主 urls.py
urlpatterns = [# blog应用路由:namespace='blog'path('blog/', include('blog.urls', namespace='blog')),# user应用路由:namespace='user'path('user/', include('user.urls', namespace='user')),
]# blog/urls.py
app_name = 'blog'  # 应用命名空间
urlpatterns = [path('', views.index, name='index'),  # 路由名'index'
]# user/urls.py
app_name = 'user'  # 应用命名空间
urlpatterns = [path('', views.index, name='index'),  # 同名路由'index'
]# 反向解析时指定命名空间
def my_view(request):# 生成blog应用的index URL:/blog/blog_index_url = reverse('blog:index')# 生成user应用的index URL:/user/user_index_url = reverse('user:index')return ...# 模板中使用
<a href="{% url 'blog:index' %}">博客首页</a>
<a href="{% url 'user:index' %}">用户首页</a>

二、视图函数

        视图函数是 Django 处理 Http 请求的核心逻辑载体 —— 它接收request对象(包含请求所有信息),与模型交互获取数据,最终返回HttpResponse对象(或其子类)作为响应

1、什么是视图函数

(1)本质:一个python函数,第一个参数必须是request(Django 封装的 HTTP 请求对象)

(2)返回值:必须是HttpResponse对象或其子类(如JsonResponse

(3)存放位置:约定放在应用的views.py文件中

(4)核心职责:①接收请求参数(URL 参数、GET/POST 数据、Cookie 等)

                           ②与模型交互(查询 / 修改数据)

                           ③渲染模板(将数据传递给 HTML)或返回 JSON 等数据

                           ④返回响应给用户

2、简单视图函数:Hello Django

最基础的视图函数仅返回一段文本,无需模板和模型:

# myapp/views.py
from django.http import HttpResponsedef hello(request):"""简单视图:返回Hello Django"""# HttpResponse(content, status=200):content是响应内容,status是HTTP状态码return HttpResponse('Hello, Django!', status=200)# 配置路由(myapp/urls.py)
urlpatterns = [path('hello/', views.hello, name='hello'),
]

在浏览器中访问 http://127.0.0.1:8000/hello/,页面会显示 Hello Django!

3、错误视图:处理异常情况

        当请求无法正常处理时(如页面不存在、权限不足),需要返回对应的 HTTP 错误响应。Django 提供了多种错误视图的实现方式

(1)直接返回错误状态码

通过HttpResponsestatus参数指定错误码,或使用 Django 封装的错误响应类(如HttpResponseNotFound):

from django.http import HttpResponseNotFound, HttpResponseForbidden# 1. 返回404(页面未找到)
def page_not_found(request):return HttpResponseNotFound('页面不存在!(404)')# 2. 返回403(禁止访问)
def permission_denied(request):return HttpResponseForbidden('您没有权限访问此页面!(403)')# 3. 直接用HttpResponse指定状态码
def bad_request(request):return HttpResponse('请求参数错误!(400)', status=400)

(2)主动抛出404异常

当需要根据业务逻辑判断是否返回 404(如 “文章不存在”),可使用get_object_or_404()快捷函数(后续会讲)或主动抛出Http404异常:

from django.http import Http404
from django.shortcuts import render
from .models import Articledef article_detail(request, pk):"""文章详情:不存在则抛出404"""try:article = Article.objects.get(pk=pk)  # 查询文章except Article.DoesNotExist:# 主动抛出404异常,Django会返回默认404页面raise Http404('该文章不存在或已被删除!')return render(request, 'article_detail.html', {'article': article})

(3)自定义错误页面

Django 默认的错误页面(如 404、500)样式简陋,实际项目中需自定义。配置步骤如下:

步骤一:修改项目设置(settings.py)

生产环境下需关闭DEBUG模式,并指定允许的域名(否则无法显示自定义错误页面):

# settings.py
DEBUG = False  # 关闭DEBUG(生产环境必需)
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']  # 允许访问的域名
步骤 2:配置错误处理器(主urls.py

在项目主urls.py中配置handler400handler403handler404handler500,指定自定义错误视图:

# 项目主 urls.py
from django.contrib import admin
from django.urls import path
from myapp import views  # 导入自定义错误视图# 配置错误处理器(必须在主urls.py中配置,子应用无效)
handler400 = 'myapp.views.bad_request'  # 400:请求错误
handler403 = 'myapp.views.permission_denied'  # 403:禁止访问
handler404 = 'myapp.views.page_not_found'  # 404:页面未找到
handler500 = 'myapp.views.server_error'  # 500:服务器内部错误urlpatterns = [path('admin/', admin.site.urls),# 其他路由...
]
步骤 3:编写错误视图(myapp/views.py
# myapp/views.py
from django.shortcuts import render
from django.views.decorators.csrf import requires_csrf_token@requires_csrf_token  # 确保CSRF令牌可用
def bad_request(request, exception):"""处理400错误:请求参数错误"""return render(request, '400.html', status=400)@requires_csrf_token
def permission_denied(request, exception):"""处理403错误:权限不足"""return render(request, '403.html', status=403)@requires_csrf_token
def page_not_found(request, exception):"""处理404错误:页面不存在"""return render(request, '404.html', status=404)@requires_csrf_token
def server_error(request):"""处理500错误:服务器内部错误(无需exception参数)"""return render(request, '500.html', status=500)
步骤 4:编写错误模板

templates目录下创建400.html403.html404.html500.html,示例404.html

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>页面未找到 - 404</title><style>.error-container { text-align: center; margin-top: 50px; }h1 { font-size: 48px; color: #dc3545; }p { font-size: 18px; margin: 20px 0; }a { color: #007bff; text-decoration: none; }</style>
</head>
<body><div class="error-container"><h1>404 - 页面不见了</h1><p>您访问的页面不存在或已被删除</p><a href="{% url 'home' %}">返回首页</a></div>
</body>
</html>

4、异步视图:处理耗时操作

Django 3.1+ 支持异步视图函数,可处理耗时操作(如调用外部 API、读取大文件)而不阻塞其他请求。只需用async def定义视图,内部通过await执行异步操作

示例:异步视图模拟耗时任务

# myapp/views.py
import asyncio
from django.http import HttpResponseasync def async_view(request):"""异步视图:模拟1秒耗时操作"""# 异步操作(如调用异步API、异步读取文件),需用await关键字await asyncio.sleep(1)  # 模拟1秒耗时(不阻塞其他请求)return HttpResponse('Hello from async view!(耗时1秒)')# 配置路由
urlpatterns = [path('async/', views.async_view, name='async_view'),
]

注意:

①异步视图仅在支持异步的服务器(如daphne)上生效,runserver(开发服务器)也支持但不建议用于生产

②若视图中调用的是同步函数(如 Django ORM 的同步操作),需用sync_to_async包装,否则会阻塞事件循环

总结

本文聚焦 Django 视图与路由的基础能力,核心知识点包括:

1、URL 路由配置:从基础映射到进阶技巧(路径转换器、正则、反向解析、命名空间),解决了 “请求如何找到对应视图” 的问题

2、视图函数:从简单文本响应到错误处理、自定义错误页面、异步视图,覆盖了 “如何处理请求并返回响应” 的核心逻辑

http://www.dtcms.com/a/422519.html

相关文章:

  • 华为 HCIA-Datacom 备考:VRP 通用路由平台原理-实操
  • 网站开发需要哪些知识展台
  • 高端网站建设服务器网站首页做一点开有动画
  • 借助串口以太网模块与三菱以太网通信处理器,实现三菱 FX3U PLC 和触摸屏通讯的案例
  • 现代控制理论4——第3章线性控制系统的能控性和能观性(1)
  • 【论文精读】Group Collaborative Learning for Co-Salient Object Detection
  • Apache NuttX 入门指南
  • MySQL进阶知识点(六)---- 存储引擎
  • 2025.8.10-学习C++(一)
  • QAxios研发笔记(一):在Qt环境下,构建Promise风格的Get请求接口
  • 【OpenGL】复杂光照理论与实践
  • Binder和IBinder
  • 标准化考场建设方案解析:全频阻断作弊防控系统介绍
  • 网站开发 团队协作h5响应式 wordpress
  • 通义万相2.5系列模型发布,可生成音画同步视频
  • Transformer实战(20)——微调Transformer语言模型进行问答任务
  • Vue3和element plus在el-table中使用el-tree-select遇到的change事件坑
  • my sql 常用函数及语句的执行顺序
  • adb安装教程(附adb命令大全详解)adb环境配置教程
  • 当贝安卓9.0_创维E900S_e910V10C_3798mv310处理器线刷烧录包可救砖带adb功能
  • SQL 执行异常排查 java.sql.SQLException:从 SQLException 说起
  • uniapp 运行/发版微信小程序
  • vue2动态实现多Y轴echarts图表,及节点点击事件
  • MySQL 数据导出及备份方法
  • 公司网站建设设计如何收费网站诊断分析
  • 网站设计技巧如何看网站是用什么程序做的
  • Pythoner 的Flask项目实践-Mapboxgl-v3全球3D地图体验之地标性 3D 建筑物(迪拜哈里发大厦三维模型展示)
  • 学习机器学习要学习和掌握哪些知识?
  • 化学专业大型语言模型——SparkChemistry-X1-13B本地部署教程:洞察分子特性,精准预测化学行为
  • qt5下载