10.1 路由系统基础
2025-02-17
- 什么是URLconf
- URLconf实现什么功能
- URL路由定义的语法
- 不同的定义方式实现了什么样的效果
- URL中参数传递的几种形式
10.1.1 认识URLconf
- 目的:定义URL与视图之间的映射表,实现将不同的URL分发给不同的视图处理函数
概念的角度理解URLconf
理解是什么;在一次HTTP请求的过程中扮演什么样的角色
创建Django项目(django-admin startproject),执行此命令就会在当前的项目中创建一份
URLconf,即urls.py文件,同时创建的settings.py文件中还定义了变量ROOT_URLCONF指向了这个URLconfURLconf(urls.py文件)
- urlpatterns:是一个列表,列表中的元素成为URL成为URL模式,每个模式定义了一个URL的基本格式。URL模式实现了两类绑定
- 第一类:URL与视图函数的绑定,及URL关联到处理方法
- 第二类:URL与URLconf的绑定,实现路由分发
- urlpatterns:是一个列表,列表中的元素成为URL成为URL模式,每个模式定义了一个URL的基本格式。URL模式实现了两类绑定
ROOT_URLCONF:即根URLconf。作为URL查找的入口
URLconf的查找,Django定义了以下两个规则
- HTTP请求中的URL被认为是一个普通的python字符串,进行匹配时不包含请求参数和域名
- URLconf不会检查HTTP请求类型,即不论GET POST PUT或HEAD,都会路由到同一个视图函数
Django推荐的路由做法:每个应用都定义自己的URLconf,并在根URLconf中声明;(URL的分级概念)
- 如:
path('post/', include('post.urls'))
- 如:
10.1.2 URL模式定义相关的函数
- 为视图函数定义URL模式,主要涉及:
path,re_path,include,register_converter
path函数
- 用于定义URL模式,一般用于定义常规的字符串路由
- (partial 是偏函数)
- path实际是对_path函数(partial中传递的第一个参数)的包装,且指定了_path函数的Pattern参数为RoutePattern
- _path的前四个参数
- route:必填参数,是包含URL模式的字符串或gettext_lazy函数(实现对字符串的惰性存储,在真正被用到时才会去翻译)的返回值
- view:必填参数,可传递两种类型
- 视图函数或基于类的视图的as_view方法的结果,此类参数在Python中称为可调用对象
- 是调用
include函数的返回值,是一个元组对象
- kwargs:选填参数,字典类型,需要给目录视图传递参数
- name:选填参数,给URL模式命令,非常有用;通常在重定向和模板中被引用到,即使修改了route,也不需要修改引用的地方
kwargs参数用法
例子:
# urls.py
path('topic/<int:topic_id>/', views_topic_detail_view, kwargs={"foo":"bar"})
# views.py
# 访问 post/topic/1/ 实际调用视图传递的参数为
topic_detail_view(request, topic_id=1, foo='bar')
# 注意
# 要求topic_detail_view视图定义的参数中包含foo- 当存在参数冲突问题时,以URL中的参数为准(默认只认URL中的参数)
re_path函数
- 定义正则表达式路由
- re_path = partial(_path, Pattern = RegexPattern)
include函数
- 用于将URLconf的完整Python路径引入另一个URLconf中
- 常见用法:在项目的跟URLconf中引入各个应用的URLconf,实现路由分发
def include(args, namespace=None)- namespace: 指定实例的命名空间,可选参数
- args的三种定义形式:module,pattern_list,(pattern_list,app_namespace)
module:是用于指定URLconf的Python路径;
path('post/', include('post.urls', namespace='bbs_post'))pattern_list:是可迭代的path或re_path实例:
path('post_2', include( [path('index/', views.IndexView.as_view()), path('hello/', views.hello_django_bbs)] ))- 这样只会包含post应用下的两个URL模式:/post_2/index和/post_2/hello
- 此类形式不能指定
namespace
(pattern_list,app_namespace):
path('post_2', include( ( [path('index/', views.IndexView.as_view()), path('hello', views.hello_django_bbs), 'post] ), namespace='bbs_post2' ))
register_converter函数
- 用于注册path函数中route参数用到的转换器
def register_converter(converter, type_name)- converter: 转换器类
- type_name:转换器名称,在route中被使用
10.1.3 路由参数的传递
1. 无参数传递
通常是欢迎页或者出错页的视图定义,不需要任何处理逻辑,直接返回结果
此类视图也称为静态路由,即URL是固定不变的,且不需要在URL中传递参数
# views.py def hello_django(request): pass # urls.py path('hello/', views.hello_django)
2. URL模式参数绑定
- 定义URL模式(path或re_path函数)时,指定kwargs,以字典的形式定义;其中的每一个键值对都将映射到视图的各个参数上去
3. 请求传参
请求参数存储在HttpRequest对象中
GET请求:参数位于URL的
?后面,格式为键值对的形式,以&连接POST请求:通过表单的形式给视图函数传递参数
在视图中获取请求参数的方式是类似的:GET请求通过HttpRequest的GET属性,POST请求通过P OST属性,在视图函数中获取GET请求的参数
def get_request(request): a = request.GET['a'] # 需要确保URL中有传递,否则有异常 b = request.GET.get('b','y') # 在URL中非必需
4. 动态路由参数捕获
- 实现方式
- 路径转换器:用在path函数中,格式:
<converter:name>- converter: 表示转换器类
- name:参数名
path('dynamic/<int:year>/<mth:month'), views.dynamic_hello)
- 正则表达式:通过分组匹配来捕获URL中的值并以位置参数的形式传递给视图,分组:
- 命名分组:
re_path('re_dynamic/(?P<year>[0-9]{4})/(?P<month>[0-9]{2}/)',views.dynamic_hello) - 未命名分组:
re_path('re_dynamic/([0-9]{4})/([0-9]{2}/)',views.dynamic_hello)
- 命名分组:
- 路径转换器:用在path函数中,格式:
10.1.4 自定义错误页面
Django给4种错误定义了“handler”处理视图
定义文件:
django/cong/urls/__init__.pyhandler400 = defaults.bad_request handler403 = defaults.permission_denied handler404 = defaults.page_not_found handler500 = defaults.server_errorhandler名称固定,不可以修改
处理错误的视图定义在:
django/views/defaults.py
自定义错误页面
- 实现过程,4个步骤
- 修改系统配置
- 定义错误页面模板文件
- 定义错误处理视图
- 配置handler
修改系统配置
自定义的错误页面只会在非调试模式下生效,所以需要修改配置文件settings.py
- (1)将DEBUG设置为False,标识当前处于非调试模式。
- (2)非调试模式下需要指定ALLOWED_HOSTS,这里将它简单地设置为['*'],代表允许所有的域名访问
定义错误页面模板文件
- 在templates下创建模板文件
- 404.html
- 400.html
- 403.html
- 500.html
定义错误处理视图
对于404错误,Django实现的是:
defaults.page_not_found自定义错误处理视图,在应用下的views.py文件中定义
# 400 def bad_request(request, exception, tempalte_name='post/400.html'): return render(request, template_name) # exception: 保存异常的信息 # 403 def permission_denied(request, exception, template_name='post/403.html'): return render(request, tempalte_name) # 404 def page_not_found(request, exception, template_name='post/404.html'): return render(request, tempalte_name) # 500 def server_error(request, template_name='post/500.html'): return render(request, tempalte_name)
配置handler
指定错误处理handler的入口,需要在项目的urls.py文件中指定
# project/urls.py handler400 = defaults.bad_request handler403 = defaults.permission_denied handler404 = defaults.page_not_found handler500 = defaults.server_error