表与表之间建关系
以图书管理系统为例
设计表
(粗糙版的思路)写出各个表,再分析关系,建立外键(加一个关联字段)/ 增加第三张关联表
Django ORM实现
一般一个 django项目 创建一个数据库
连接MySQL
两步(mysql连接配置、... pymysql.install_as_MySQLdb())
创模型表
先写一部分字段结构,再补充
app 下的models.py 整个文件拷过来
如何创建多对一 的外键关系?(ForeignKey、外键字段 _id 自动加(自己指定了也还会加一个))
如何创建多对多 的第三张表?(两种方式,直接建模型类、 ManyToManyField)
自动第三张表、不会在表里多出这个字段
如何创建一对一 的外键关系?(OneToOneField、也会自动在外界字段后面加 _id)
to=‘publish’关联字段的 ‘publish’ 和 直接 publish 有位置的关系(后者要求先出现了才能用)
本周作业,图书管理系统(至少书籍表的增删改查)
迁移同步到数据库
好像是 migrate 创建的表(自带的那堆表)
django请求生命周期
(要会画这张图)
wsgiref(web服务网关接口) 模块不支持高并发(1000不到),只用于本地测试,上线之后会换成 uwsgi 模块
路由层
url 路由匹配(基于正则、django 1.x特有)
匹配规则
urls 中url() 方法,第一个参数其实是一个正则表达式(匹配规则 和 == 是不一样的)
一旦前面的正则匹配到了内容,就不会再继续往下匹配了,而是直接执行对应的视图函数
带来的问题
正是由于上面的特性,当你的项目特别庞大的时候, url 的先后顺序也是你需要考虑的,极有可能出现 url 错乱的现象
不加斜杆也能匹配的原理(django 二次匹配)
django 在路由匹配的时候,当你在浏览器中没有敲最后的斜杆,django会先拿着你没有敲斜杆的结果去匹配,如果没有匹配上,会让浏览器在末尾加斜杆,再发一次请求,再匹配一次,如果还匹配不上,才会返回 404
如果你想取消该机制,不想做二次匹配,可以在 settings.py 中配置,但还是加上比较好(方便嘛)
... 省略一堆配置
# APPEND_SLASH = False # 该参数默认是 True
... 省略一堆配置
利用正则限制 url
符合正则的几个 url访问
/dasdadtest/
/test/test/dasda/ae
限制结尾了 $ ,那 get 的 ?参数呢?
限制空 r'^$'
--> 首页(127.0.0.1:8080
)
不存在路径自定义 404 页面 --> r''
请求不存在的 url 会去执行他的视图函数(一般放在最后) --> 会导致 testaddd/ 没加斜杆的这个问题(像环境变量一样全部一遍,不行再去加斜杠再来一次) ---> 一般 404 页面不是这么做的
url 分组相关
无名分组
视图函数定义哪里需要多写一个位置参数占位
会把分组结果当做位置参数传给视图函数
有名分组
视图函数定义的时候需要多写一个参数(与分组名同名)
无名分组有名分组不能混合使用(但是...)
回顾: 函数定义的参数原则之一 --> 位置参数必须放在关键字参数的前面(所以有名分组要防在无名分组后面)
但是,同一种可以有多个(场景:多个有名分组 或者 多个无名分组)
url 反向解析 *****
本质:其实就是给你返回一个别名能够返回对应 url 的地址
应用场景 / 有什么用
根本作用:在改变 url 路由配置的时候,其他引用了这个路由的地方能自动解析,不受影响
对于前端,以不变应万变
html 网页中的链接(页面跳转、数据获取接口(只要是发起请求的,都要有一个地址,可以通过解析来配置这个url 地址,在后端 url 里一改,那些连接就自动解析去更改了))
对于后端,也是以不变应万变(主要针对的是 redirect 重定向页面,直接去匹配 url)
后端的 redirect 函数中放的一般都是 url , 如果需求要变动 url ,那所有要 redirect 这个 url 的地方就都要改过来才行(那如果视图函数太多了,久远了,忘记了,改起来漏了一个,对于上线的项目来说,那都不是小事),我们就可以利用 url 反向解析,在后端利用别名获取到(可能会改动的)url 放到变量里,把这个变量放到 redirect 里即可,这样就不会因为 url 的改动而影响到其他功能了
目前接触的解析小回顾总结
其他可能要解析的也想一下,去查一下,学习一下怎么配置(作为技能点,后期用到了岂不是很棒?)
解析什么 | 场景 | 写法 |
---|---|---|
静态资源文件路径动态解析 | 可以随意改静态资源的 url (....好处再补充) | 记不清了,回顾下 {{ load static 。。。?}} |
url 路由动态解析 | 统一修改访问的 url(接口等的) | urls 、前后端都需要做响应的处理 |
好像这两天学的还有一个来着? | ||
不知道有没有其他的,待补充 |
实际操作
改 a 标签的 url --> 有1000个 咋整
给当前 url 和 视图函数 起一个别名
- 后续通过这个别名动态解析出来
反向解析
后端
后端可以在任意位置、任意视图函数通过 reverse 反向解析出对应的url( 导 三板斧那里,再导一个 reverse)
reverse(‘kk(刚起的别名name)’)
前端
{% url 'kkk(刚配的别名name)' %}
反向解析无名分组
可以让视图函数直接拿到 url 中的参数(非 get 方式传参,比request.GET.get(‘参数名’) 的更好用),更加形象的还是看下面的便捷之处
这下面的数字,通常是 数据的id值,这样在 url里就能拿到,不需要在 request.GET.get(‘id’) 了
分组的便捷之处(伪代码)
(以获取商品信息为例,随你举什么形象的例子啦)
在配 url 的时候使用分组
可以给视图函数直接传递形(实?)参,函数可以直接拿到这个分组的值(一般是用户id、商品id(各种id)),可以直接进行数据库的操作(一般是根据 id 查数据),然后 把数据对象通过 render 渲染到 html (模板语法可以使用该数据对象)
在 html 中可以用模版语法,给 a 标签等要跳转页面、请求数据(发请求)的地方使用反向解析(所以后续不需要担心 url 改动让这些链接失效),把 id 等内容放到 url 后面( /shopList/123251(比如这是商品id)),可以方便后续 url 解析到视图函数时可以直接拿到对应的id 进行处理
前端,反向解析后面 随便加个数字
后端反向解析,也是指定数字
*args 让函数可以随便接收参数(视图函数)
后端利用别名反向解析出 url :reverse(‘kk’, args=(1,))
作业
用反向解析完成用户的编辑和删除(前后端都要用)
有名分组反向解析
url 对应的视图函数可以用关键字参数拿到解析到的值(后续完善时可以下 html 中传参 连接显示的是什么?(/kkk/year=1 还是 /kkk/year:1 ?))
urls.py
同无名分组反向解析一样的用法(无名解析的方式也支持有名分组)
后端
前端
但还是推荐 无名分组的反向解析,就只需要记一套做一套,减少脑容量
反向解析取别名特别强调
在同一个应用(app)下,别名不能重复
小疑惑
为什么有多级url? 这个涉及到路由分发
整个django 控制路由,不同应用下有不同的路由
user/index admin/index 所以后面加肯定是有应用场景的
路由分发 *****
为什么有路由分发
当你的 django 项目特别庞大的时候,路由与视图函数对应关系特别特别多,那么你的总路由 urls.py 代码太过冗长,不易维护
每一个应用(app),都可以有自己的 urls.py, static 文件夹, templates 文件夹
也正是基于上述条件,可实现多人分组开发,等多人开发完成之后,我们只(仔细想想有哪些牵扯到的地方,要一块改的哦,我还没经验)需要创建一个空的 django项目,然后将多人开发的app全部注册进来,在总路由实现一个路由分发,而不再做路由匹配(来了之后,我只给你分发到对应的app中)
如何配置路由分发
导入 include(url后面)
from django.conf.urls import url, include
导入对应APP urls 文件中的 urls 并取别名 (as)
配置分发
2、3 如下图
简便写法(原理 ---> importlib 动态导入模块(可能 django 项目内置了,直接就可以用))
在路由分发中 url 路由配置的注意点
总路由中,一级路由的后面千万不能加 $ --> 正则匹配知识点
当你的应用下的视图函数特别多的时候,你也可以建一个 views 文件夹,然后再根据功能的不同,细分,去做不同的 py 文件 --> 解耦合 的思想,尽可能地拆分(怎么形容的?再好好描述一下)
合并应用
注册app
路由分发
名称空间(了解,避免 url 同别名)
解决同一个django 项目中 不同 app 中的 路由配置 url 起了相同的别名无法通过 别名 正确解析 url
(默认解析到的是最后一个(最后一个 app ? 感觉更像是总路由那里放最后(试试是不是最先?)匹配路由的 app))的问题
多个APP起了相同的别名(协同开发还是可能出现的),这个时候用反向解析,这是并不能自动识别应用前缀
如果想避免这种问题的发生
起别名(为了解决别名冲突)
默认情况下 --> 反向解析会出现解析不出来的情况(默认是最后一个(/app02/index))
指定名称空间
或者 指定名称空间
总路由
后端
前端
避免取冲突的别名
起别名的时候不要冲突即可,一般情况下在起别名的时候通常简易以应用名作为前缀
页面伪静态(seo 优化)
静态网页:数据是写死的,万年不变
博客园文章 url 后缀 .html 看着像纯网页,写死的, 这样的就是伪静态
为什么要做伪静态
伪静态网页的设计是为了增加百度等搜索引擎SEO查询力度
其实所有的搜索引擎本质上都是一个巨大的爬虫程序,把所有的数据爬到了他们的服务器,再展示出来
网站优化相关 通过伪静态确实可以提高你的网站被查询出来的概念,但是再怎么优化已抵不过RMB玩家
如何实现伪静态
直接 用 /index.html 来作为路由匹配规则
eg:url 加 .html --> /index/ --> index.html
python项目虚拟环境的创建与使用
一般情况下,我们会给每一个项目配备该项目所需要的模块,其他的,不需要的模块一概不装
虚拟环境就类似于为每个项目项目量身定做的解释器环境
如何创建虚拟环境
每创建一个虚拟环境,就类似于你又下载了一个全新的python解释器(所以虚拟环境也不要创太多,还是占用硬盘资源的)
创建
图里不是使用,是创建,重截图的时候改过来
虚拟环境
一删了就没了,不安全
自己安装其他环境(模块等) django pymysql ...
使用虚拟环境创建项目
前提是前面创建虚拟环境的时候勾上了允许其他项目使用
django不同版本url路由配置的区别
django1.x 跟 django 2.x 版本区别
- urls.py 中路由匹配
- 1.x用的是 url,第一个参数是正则表达式,正则匹配
- 2.x用的是 path,且第一个参数不再是正则表达式了,而是精准匹配,写什么匹配什么
- 当你使用 2.x 不习惯时,还可以用 re_path, 2.x 的 re_path 就是 1.x 中的 url
- 虽然 2.x 中 path不支持正则表达式,但是它支持五种默认的转换器
2.x path 支持的转换器
默认有五个转换器,感兴趣的自己可以课下去试一下
str,匹配除了路径分隔符(/) 之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如075194d3-6885-417e-a8a8-6c931e272f00 。
path,匹配任何非空字符串,包含了路径分隔符(/)
(不能用? )
小案例
django 2.x path 自定义转换器
视图层
小白必会三板斧(前面有文章中又详细例子,这里就不展开了)
HttpResponse
render
redirect
django 视图函数必须要返回一个HttpResonse 对象 √
看源码发现:render、redirect 返回的也还是一个 HttpResponse 对象,继承了 HttpResponse,所以肯定是 HttpResponse 对象
直接返回 json数据给前端(前后端分离会用到)
数据交互、跨语言 --> 通常用 json 格式
下面两种方式都要注意编码方式(json 默认编码,要指定 ensure_ascii)
前后端分离
前端一个人干(前端把 json 转成自定义对象)
JSON.stringify() -- json.dumps
JSON.parse() -- json.loads
后端另一个人干 (python 后端用字典)
后端只负责产生接口,前端调用该接口能拿到一个大字典
后端只需要写一个接口文档(url 有几个参数,能拿到什么数据。。。),里面描述字典的详细信息以及参数的传递
返回 json 格式数据给前端(前端拿到的也还是字符串,不过可以利用函数解析成json)
利用 json 模块 + HttpResponse 返回 json 数据
利用 JsonResponse 返回 json 数据(Django自带的,要导一下)
下面的中文会乱码
解决乱码
看源码,找到机会( json_dumps_params )
解决方案
扩展 JsonResponse 支持的数据类型
这里举例返回列表
如果返回的不是字典,只需要修改 safe参数 为 false 即可
上传文件
form表单上传文件需要注意的事项
enctype 需要由默认的 urlencoded 要变成 formdata(这两个模式看下网页上到底什么样的)
method 请求方式改为 post
新建的项目要用 post 请求 ,要把 settings.py 中的 CSRF 中间件 注释掉
如果 form 表单上传文件,那么后端需要在 request.FILES.get(‘myfile(input标签的name)’)
用 .get 取,也是列表最后一个,拿到的是一个对象
file 对象
有很多属性方法,后续研究下(后期工作中项目里肯定会用到文件上传处理的)
将上传的文件写入后端
.chuncks() 获取可迭代文件对象(推荐 .chuncks() ) 但写不写用起来都是一样的 文件对象本身就可迭代对象(搜一下为什么要用 .chuncks() ? )
request 的其他方法
request.method
request.GET
request.POST
request.FILES
request.path
request.get_full_path
本周作业
图书管理系统