Django进阶之路由层和视图层
Django的路由系统
【1】什么是URL配置(URLconf)
- URL调度器 | Django 文档 | Django (djangoproject.com)
- URL配置(URLconf)就像Django 所支撑网站的目录。
- 它的本质是URL与要为该URL调用的视图函数之间的映射表。
- 你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。
【2】基本语法
(1)Django1.x语法
(2)Django2.x+
- 注意
- 要从 URL 中取值,使用尖括号。
- 捕获的值可以选择性地包含转换器类型。比如,使用
<int:name>
来捕获整型参数。如果不包含转换器,则会匹配除了/
外的任何字符。 - 这里不需要添加反斜杠,因为每个 URL 都有。比如,应该是
articles
而不是/articles
。
(3)参数说明
- 路径名:
- 在浏览器端口后请求的路径名
- views视图函数:
- 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
- 参数:
- 可选的要传递给视图函数的默认参数(字典形式)
- 别名:
- 一个可选的name参数
【3】请求示例
/articles/2005/03/
会匹配 URL 列表中的第三项。Django 会调用函数views.month_archive(request, year=2005, month=3)
。/articles/2003/
将匹配列表中的第一个模式不是第二个,因为模式按顺序匹配,第一个会首先测试是否匹配。请像这样自由插入一些特殊的情况来探测匹配的次序。在这里 Django 会调用函数views.special_case_2003(request)
/articles/2003
不匹配任何一个模式,因为每个模式要求 URL 以一个斜线结尾。/articles/2003/03/building-a-django-site/
会匹配 URL 列表中的最后一项。Django 会调用函数views.article_detail(request, year=2003, month=3, slug="building-a-django-site")
。
【4】使用正则表达式
- 如果路径和转化器语法不能很好的定义你的 URL 模式,你可以可以使用正则表达式。如果要这样做,请使用
re_path()
而不是path()
。 - 在 Python 正则表达式中,命名正则表达式组的语法是
(?P<name>pattern)
,其中name
是组名,pattern
是要匹配的模式。 - 这里是先前 URLconf 的一些例子,现在用正则表达式重写一下:
- 这实现了与前面示例大致相同的功能,除了:
- 将要匹配的 URLs 将稍受限制。比如,10000 年将不在匹配,因为 year 被限制长度为4。
- 无论正则表达式进行哪种匹配,每个捕获的参数都作为字符串发送到视图。
- 当从使用
path()
切换到re_path()
(反之亦然),要特别注意,视图参数类型可能发生变化,你可能需要调整你的视图。
【一】路由匹配
【1】路径参数相似
无法跳转到
testadd
- url方法第一个参数是路径参数
- 只要第一个参数能够匹配到内容,就会立刻停止匹配,执行视图函数
【2】解决路径参数相似问题
- 在尾部加一个/
- 在输入url的时候会默认加一个/
- 一次匹配不行,那就加一个/ 再尝试一次
【3】路由系统自动添加 /
- 在配置文件中,有一个参数可以帮助我们干这件事
- 当设置为
True
时,如果请求的 URL 不符合 URLconf 中的任何模式,并且不以斜线结尾,则会发出一个 HTTP 重定向到相同的URL,并附加一个斜线。 - 注意,重定向可能会导致 POST 请求中提交的任何数据丢失。
APPEND_SLASH
的配置只有在安装了CommonMiddleware
的情况下才会使用(参见 中间件)。也请参见PREPEND_WWW
。
【4】完整的路由匹配
- 这才是完整版的路由匹配格式
- 匹配首页的路由格式
【二】无名分组
- 分组就是将某段正则表达式用
()
括起来
- 无名分组就是将括号内正则表达式匹配到的内容当做位置参数传给后面的视图函数
【三】有名分组
- 可以给正则表达式起一个别名
- 有名分组就是将括号内正则表达式匹配到的内容当做关键字参数传给后面的视图函数
【四】无名有名混用
- 无名分组和有名分组不能混用
- 但是同一个分组可以使用多次
【五】反向解析
【0】反向解析的本质
-
先给路由起一个别名,然后,通过一些方法去解析别名,可以得到这个别名对应的路由地址
-
先给路由与视图函数起一个别名
【1】后端反向解析
【2】前端反向解析
【3】无名分组的反向解析
- 有名分组和无名分组的反向解析是一样的
【六】路由分发
【1】前言
- Django每一个应用都可以拥有属于自己的
- templates文件夹
- urls.py
- static文件夹
- 正是基于上述的特点,Django可以很好的做到自己的分组开发(每个人只写自己的app)
- 最后只需要将所有的app拷贝到新的文件,并将这些APP注册到配置文件中,然后再利用路由分发的特点,将所有的APP整合起来
- 当一个项目中的URL特别多的时候,总路由urls.py的代码非常冗余而且不好维护,这个时候就可以利用路由分发来减轻总路由的压力
- 利用路由分发之后,总路由不再干预路由与视图函数的直接对应关系
- 而是做一个分发处理
- 识别当前的url是属于哪个应用下的,直接分发给对应的应用去处理
【2】语法
- 通常,我们会在每个app里,各自创建一个urls.py路由模块,然后从根路由出发,将app所属的url请求,全部转发到相应的urls.py模块中。
(1)方式一:转发app下的urls
- 例如,下面是Django网站本身的URLconf节选。 它包含许多其它URLconf:
- 路由转发使用的是
include()
方法,需要提前导入,它的参数是转发目的地路径的字符串,路径以圆点分割。 - 每当Django 遇到
include()
时,它会去掉URL中匹配的部分并将剩下的字符串发送给include的URLconf做进一步处理,也就是转发到二级路由去。
(2)方式二:转发url列表
- 另外一种转发其它URLconf的方式是使用一个path()实例的列表。 例如,下面的URLconf:
- 在此示例中,
/credit/reports/
URL将由credit_views.report()
视图处理。 - 这种做法,相当于把二级路由模块内的代码写到根路由模块里一起了,不是很推荐。
【3】示例
(1)总路由
(2)子路由
【4】传递额外的参数给include()
- 类似上面,也可以传递额外的参数给include()。参数会传递给include指向的urlconf中的每一行。
- 例如,下面两种URLconf配置方式在功能上完全相同:
django/urls.py
【七】名称空间
【1】引入
- 当多个应用出现相同的别名,反向解析不会自动识别应用前缀
- 正常情况下的反向解析是不能识别前缀的
【2】使用
【八】伪静态
- 静态网页
- 数据是写死的
- 伪静态
- 将一个动态网页伪装成静态网页
- 伪装的目的在于增大本网站的seo查询力度
- 并且增加搜索引擎收藏本网页的概率
- 搜索引擎本质上就是一个巨大的爬虫程序
总结:无论怎么优化,怎么处理,始终还是干不过RMB玩家
【九】虚拟环境
- 在正常开发中,我们会给每一个项目独有的解释器环境
- 该环境内只有该项目用到的模块,用不到的一概不装
【1】虚拟环境
- 每创建一个虚拟环境就类似于重新下载了一个纯净的python解释器
- 但是虚拟器不建议下载太多,创建虚拟环境是需要消耗磁盘空间的
【2】模块管理文件
- 每个项目都需要用到很多模块,并且每个模块的版本可能是不一样的
- 这种情况下我们会给每一个项目配备一个requirements.txt文件,里面存放着我们这个项目所安装的所有模块及版本
- 只需要一条命令即可安装所有模块及版本
【3】模块文件导出和安装
(1)导出项目模块文件
- 这行命令的含义是 "freeze"(冻结)当前环境中的所有已安装包及其版本信息,并将其输出重定向到
requirements.txt
文件中。 - 执行此命令后,
requirements.txt
将列出你项目所需的全部依赖及其对应版本号。
(2)安装项目模块文件
- 这将按照
requirements.txt
中列出的顺序及版本要求安装相应的 Python 包。
【十】Django版本的区别
【1】路由匹配规则
- Django1.x路由层使用的是url方法
- 在Django2.x版本以后在路由层使用的是path方法
- url() 第一个参数支持正则
- path() 第一个参数不支持正则,写什么就匹配到什么
【2】正则匹配规则
- 在Django2.x以后也可以使用正则表单式,但是使用的方法是re_path
【3】路径转换器
(1)初识
- 虽然path不支持正则,但是其内部支持五种转换器
(2)五种转换器
- str
- 匹配除了 '/' 之外的非空字符串。
- 如果表达式内不包含转换器,则会默认匹配字符串。
- int
- 匹配 0 或任何正整数。返回一个 int 。
- slug
- 匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。
- 比如,building-your-1st-django-site 。
- uuid
- 匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。
- 比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。
- path
- 匹配非空字段,包括路径分隔符 '/' 。
- 它允许你匹配完整的 URL 路径而不是像 str 那样匹配 URL 的一部分。
【4】自定义转换器
- Django支持自定义转换器
(1)初识
- 转换器是一个类,包含如下内容:
- 字符串形式的
regex
类属性。 to_python(self, value)
方法,用来处理匹配的字符串转换为传递到函数的类型。如果没有转换为给定的值,它应该会引发ValueError
。ValueError
说明没有匹配成功,因此除非另一个 URL 模式匹配成功,否则会向用户发送404响应。- 一个
to_url(self, value)
方法,它将处理 Python 类型转换为字符串以用于 URL 中。如果不能转换给定的值,它应该引发ValueError
。ValueError
被解释为无匹配项,因此reverse()
将引发NoReverseMatch
,除非有其他 URL 模式匹配。
- 字符串形式的
Changed in Django 3.1:
支持引发
ValueError
以表示没有匹配项被添加。
(2)自定义转换器示例
-
在app01下新建文件
path_ converters.py
(文件名可以随意命名)
(3)使用自定义转换器
-
在urls.py中,使用
register_converter()
将其注册到URL配置中:
(4)转换器使用示例
app01/path_converters.py
urls.py
-
app01/views.py
-
测试
【十一】Django返回JSON格式的数据两种方式
【1】第一种方式json模块序列化
【2】第二种
【十二】form表单上传下载文件数据
form表单上传数据以及后端如何获取
【1】数据准备
- 路由urls.py
- views
- 前端register_two.py
- 后端没有了avatar对应的键和值
【2】优化-后端获取form的表单文件数据
【十三】request对象方法补充
【1】request.method
request.method
:该方法返回客户端用于发起请求的HTTP方法。- 例如,可以是'GET'、'POST'、'PUT'、'DELETE'等。
- 您可以使用该方法来确定请求的类型,并相应地执行特定操作。
【2】request.POST
request.POST
:该属性是一个类似字典的对象,包含了请求中通过POST方法发送的所有参数。- 这些参数通常是通过HTML表单发送的。
- 您可以使用参数的名字作为键来访问单个参数,例如
request.POST['username']
。
【3】request.GET
request.GET
:类似于request.POST
,该属性包含了请求中通过GET方法发送的所有参数。- 这些参数通常会附加在URL之后,以问号分隔。
- 您可以使用参数的名字作为键来访问单个参数,例如
request.GET['page']
。
【4】request.FILES
request.FILES
:该属性是一个类似字典的对象,包含了请求中通过文件上传组件发送的所有文件。- 当表单中包含文件上传字段时,通过
request.FILES
可以访问上传的文件。 - 您可以使用文件的名字作为键来访问单个文件,例如
request.FILES['file']
。
【5】request.path
只能获取到路由地址,无法获取到参数
request.path
:该属性表示请求URL中的路径部分。- 它包含在域名之后,在任何查询参数之前。
- 例如,如果请求的URL是"http://example.com/foo/bar/",那么
request.path
将为"/foo/bar/"。
【6】request.path_info
只能获取到路由地址,无法获取到参数
- 用于表示请求URL的路径部分,不包括域名和查询参数。
- 与
request.path
相比,request.path_info
更加原始和未经解析。 - 它保留了URL路径中的任何编码、特殊字符或斜杠等信息。
- 例如,对于以下请求URL:"http://example.com/foo/bar/?page=2",
request.path_info
的值将是 "/foo/bar/"。 - 通常情况下,您可以使用
request.path
来获取丢弃域名后的路径,而使用request.path_info
来获取原始的、未解析的路径。这在某些情况下非常有用,例如当您需要对URL进行一些自定义操作或路由处理时。
【7】request.get_full_path()
即能获取到路由地址又能获取到完整的路由地址后面的参数
request.get_full_path()
:该方法返回请求URL的完整路径,包括路径部分和任何查询参数。- 当您需要将完整URL作为字符串使用时,这个方法非常有用。
- 例如,如果请求的URL是"http://example.com/foo/bar/?page=2",
request.get_full_path()
将返回"/foo/bar/?page=2"。
【十四】CBV和FBV
- 视图函数既可以是函数也可以是类
- 我们之前写过的都是基于函数的view,就叫FBV。
- 还可以把view写成基于类的。
【1】FBV
【2】CBV
- class类和路由之间的映射关系
(1)路由
- 在视图函数引入一个类
- 在路由中注册路由和视图类之间的映射关系
(2)视图
(3)小结
- 选择使用 FBV 还是 CBV 取决于具体的需求和个人偏好。
- FBV 相对简单直观,适合编写简单的视图逻辑;
- 而 CBV 可以通过继承和重写类来实现代码复用和可扩展性,适用于复杂的视图处理场景。
- 在实际开发中,可以根据需求选择适合的方式来编写视图处理函数或类。
【十五】CBV源码剖析
- 当我们启动Django项目时
- 会自动触发路由中的方法,调用 as_view 方法并自执行
- 在执行后我们查看 as_view 方法的源码 发现
- 在依次给我们的对象赋值后,最终返回了一个自执行的 dispatch 方法
- 于是我们又去查看了 dispatch 方法
- 在 dispatch 内部 ,先是将请求方式转换并进行校验
- 然后开始校验需要调用的方法的调用位置,校验成功并拿到需要执行的方法执行
- 在自己写的类中如果有相关的方法,会首先调用我们重写的类方法,并返回执行结果
- 如果自己的类里面没有该方法 会去自己的父类中调用 父类的方法
- 如果父类 以及 基类 都找不到则报错,抛出异常
- 如果自己的类里面没有该方法 会去自己的父类中调用 父类的方法
【十六】CBV添加装饰器
【1】给FBV加装饰器
- FBV本身就是一个函数,所以和给普通的函数加装饰器无差:
【2】CBV添加装饰器的三种方式
- 类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。
- Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
(1)第一种
(2)第二种
(3)第三种
__EOF__

本文作者:Fredette
本文链接:https://www.cnblogs.com/Fredette/p/18064694.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/Fredette/p/18064694.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)