转自 李英俊小朋友千锋Django学习笔记
[TOC]
写在前面
- 学习链接:Python 900集(学完可就业/2019版):
[200集: 358集],共159集
- 感想|摘抄:
- 优秀的程序员:
- 松耦合、解耦合
- 高内聚
- Django版本:1.1
- rest_framework 最佳实践工程:DjangoREST
- 优秀的程序员:
- 学习的时候遇到的问题:
1. MVC和MTV
-
虚拟化技术
- 虚拟机
- 虚拟容器
- Docker
- 虚拟环境
- Python专用
- 将Python依赖隔离
-
MVC:一种软件设计典范,核心思想:解耦。
- 降低各个模块之间的耦合性,方便变更,更容易重构代码,最大程度实现了代码的重用。
Model:用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法,是Web应用程序种用于处理应用程序的数据逻辑部分,Model通常只提供功能新的接口,通过这些接口可以获取Model的所有功能。
View:负责数据的显示和呈现,View是对用户的直接输出。
-
Controller:负责从用户端收集用户的输入,可以看成提供View的反向功能,主要处理用户交互。
-
Django中的MVC
-
MTV:
- 本质上与MVC没有什么差别,也是各组件为了保持松耦合关系,只是定义上有些许的不同。
- Model:负责业务对象与数据库(ORM)的对象。这里orm是指,把model中的代码翻译为各个数据库的sql语言。
- Template:负责把页面站视给用户
- View:负责业务逻辑,并在适当的时候调用Model和Template
- 注意:这里的View跟MVC的View完全不一样,要类别的话,MVC的V对应MTV的T,同理,C对应V
注意:Django中还有一个url分发器(也可以叫做路由),主要用来将一个个URL页面的请求分发给不同的View进行处理,View再调用响应的Model和Template。
-
MTV设计模式:
2. Django简介
新建一个项目:
django-admin startproject [项目名称]
创建一个应用:
python manage.py startapp [app名称]
运行一个应用:
python manage.py runserver
-
SQLite:
- 轻量级的嵌入式的数据库
- 特点:小
- 场景:
- 常用场景:Android、IOS、WP
- 数据库常规操作相似度和MySQL达95%
-
settings.py中需要注意的设置:
-
ALLOWED_HOSTS = ["*"]
:这里是为了让所有人都能够访问这个服务器,如果想要其他的电脑也能通过局域网方问到你的项目,就需要运行的时候输入:python3 manage.py runserver 0:8000
,记住了,我就运行成功了嘻嘻(我在linux上建的服务器,这里是用win10连接的,成就感爆棚):这里说个题外话,如果上面还是不行的话,就可能是防火墙的原因了:
如果要想别人能够方问呢,除了ALLOWED_HOSTS设置之外,还要关闭防火墙
-
如果你百度关闭linux防火墙的话,会发现输入命令之后各种找不到,所以需要先安装防火墙,参考链接,我安装好后显示如下:
然后就可以查看防火墙状态啦:
sudo ufw status
最后,关闭防火墙:
sudo ufw disable
LANGUAGE_CODE = 'zh-hans'
:这里将语言设置为中文;注意,这里需要注意的是,要用-
而不是下划线_
,否则会报错,这是因为:版本更新后Django项目setting.py中的LANGUAGE_CODE设置变了TIME_ZONE = 'Asia/Shanghai'
:这里将时间区域设置为中国的上海
-
-
运行后(舒服~):
-
运行的时候发现,会提示没有迁移数据库的警告,所以下面要进行一段数据库迁移的操作:
-
问题1:PyCharm右键SQLite找不到As Data Source选项:我按照视频步骤来,右键就是死活找不到这个选项。
解决方案也很简单,就是选这里就会出现老师说的那个选项了(如果点击测试链接需要下载驱动,直接下载就完了):
-
连接数据库后,打开pycharm下面的terminal,
输入:
python manage.py makemigrations
并输入:
python manage.py migrate
;再启动服务器:python manage.py runserver
,现在就没有警告啦。
-
3. MTV简单流程
-
实现一个路由
- urls中-参数
- 匹配规则:正则
- 视图函数:对应的views中的一个函数,没有括号
- urls中-参数
-
去views实现对应的视图函数
- 第一个参数是request
- 永远记得返回Response
-
html快捷输入
- ul>li
- ul*5
- ul>li*5
- 记住最后一定要按tab键
-
创建模板的第一种方法:
- 在app目录中,在pycharm右键templates,设置为模板路径
- 同时,需要在
settings.py
中给INSTALLED_APPS
注册app名
-
创建模板的第二种方法(在开发中使用这种,因为模板是可以集成和复用的):
- 在项目目录下,新建templates,并设置为模板路径
- 同时,需要在
settings.py
中给TEMPLATES
的DIRS
添加os.path.join(BASE_DIR, 'templates')
-
创建第二个App:
python manage.py startapp Two
然后需要在
settings.py
中给INSTALLED_APPS
增加新增的app名 -
路由优化配置:
- 项目如果逻辑过于复杂,可以进行拆分。
- 拆分为多个App
- 继续拆分路由器urls
- 在App中创建自己的
urls.py
,设置urlpatterns
,路由规则列表 - 在urls中进行子路由的包含
- 在App中创建自己的
- 子路由使用
- 跟路由规则 + 子路由规则
4. 和Model的简单对接
-
实现数据增删改查
models:使用了ORM技术,Object Relational Mapping,对象关系映射,用于实现面像对象编程语言里不同类型系统的数据之间的转换。可以简单理解为翻译机。
-
ORM将业务逻辑和SQL进行了一个解耦合
object.save()
object.delete()
-
关系型数据库
- DDL:Database Define Language
- 通过models定义实现数据库表的定义
-
数据操作:
- 增删改查
- 存储:
save()
- 查询:
Class.objects.all()
、Class.objects.get(pk=xx)
- 更新:基于查询,查好的对象修改属性后
save()
- 删除:基于查询,调用
delete()
ctrl + P:参数提示
-
更换数据源sqlite为mysql
-
settings.py
中将数据源信息换为mysql -
利用pycharm的工具连接mysql数据库
-
执行迁移:
python manage.py migrate
,这个时候会报错没有mysqldb: -
连接mysql的驱动:
- mysqlclient:2、3都能直接使用, 致命缺点:对mysql安装有要求,必须在指定位置存在配置文件
- python-mysql:对2支持很好,3不支持
- pymysql:2、3都支持,并且它还可以伪装成前两个库(啊,这?)
现在就要安装pymysql:
pip install pymysql
,这里建议用pip给mysqlclient包升个级,不然后面还会报错的:pip install --upgrade mysqlclient
-
把pymysql伪装成MySQLdb:
import pymysql pymysql.install_as_MySQLdb()
相信我这一步,不要做,只需要安装
mysqlclient
就可以了,不需要伪装MySQLdb,不然的话,会报错mysqlclient
不符合版本要求,因为pymysql
的版本是0.10.1,所以伪装之后的mysqlclient
也是0.10.1。伪装报错的原因:mysqlclient 1.4.0 or newer is required; you have 0.10.0.
-
再执行迁移操作:
python manage.py migrate
,成功!同时,这些表也迁移过来了(就十分神奇,我服了~):
-
然后启动服务,获取四个学生
-
再查看
-
-
测试数据模型
进入这个项目的shell:
python manage.py shell
集成了python环境的shell终端
通常在终端中做一些调试工作
-
如何看代bug:
- 看日志:先看第一条、再看最后一条
- 梳理思路:程序在哪一个位置和预期出现了偏差
表关系:1:1、1:M、M:N
-
建立级联关系
from django.db import models class Grade(models.Model): g_name = models.CharField(max_length=32) class Student(models.Model): s_name = models.CharField(max_length=16) # 外键、级联关系 s_grade = models.ForeignKey(Grade, on_delete=models.PROTECT)
-
这里可能会报错:
TypeError: __init__() missing 1 required positional argument: 'on_delete'
- 这是因为你用的django版本太新了,创建外键的时候需要指定,如果删除了,应该怎么处理,详见参考链接
-
然后就是要迁移哦:
python manage.py makemigrations
python manage.py migrate
-
经典重现
-
CS/BS
-
MVC
-
MTV
-
Django
-
5. Model
在企业开发中,我们通常都是从数据开始开发的
-
数据库中的数据类型
- 字符串
- 数字
- 日期时间
-
属性命名规则
- 遵循标识符规则
- 由于django的查询方式,不允许使用连续的下划线
逻辑删除:对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False
-
字段类型
- AutoField
- CharField
- TextField
- IntegerField
- DecimalField:高精度
- FloatField
- BooleanField
- NullBooleanField
- DateField
- TimeField
- DateTimeField
- FileField
- ImageField:继承FileField,图片格式校验
-
字段选项
- null
- blank
- null是数据库范围的概念,
None
;blank是表单验证范畴,""
- null是数据库范围的概念,
- db_column
- db_index
- default
- primary_key:主键约束
- unique:唯一约束
-
关系
- ForeignKey:一对多
- ManyToManyField:多对多
- OneToOneField:一对一
-
模型成员objects
- Django默认通过模型的objects对象实现模型数据查询
- Django有两种过滤器用于筛选记录
- filter:返回符合筛选条件的数据集
- exclude:返回不符合筛选条件的数据集
- 多个filter和exclude可以连接在一起查询
-
快捷键
- .re 快捷生成return
- 多用
.
看看世界的美好
-
方法
- 对象方法
- 可以调用对象的属性,也可以调用类的属性
- 类方法
- 不能调用对象属性,只能调用类属性
- 静态方法
- 啥都不能调用,不能获取对象属性,也不能获取类属性
- 只是寄生在我们这个类上而已
- 对象方法
-
在管理器上调用方法返回查询集,查询经过过滤器筛选返回新的查询集,所以可以写成链式调用,返回查询及的方法成为过滤器:
-
all()
:返回所有数据 -
filter()
:返回符合条件的数据 -
exclude()
:过滤掉符合条件的数据 -
order_by()
:排序 -
values()
:一条数据就是一个字典,返回一个列表
-
-
状态码
- 2xx:请求成功
- 3xx:转发或重定向
- 4xx:客户端错误
- 5xx:服务器错误,后端开发人员最不想看到的
产品上线后需要将
DEBUG
改为True
-
获取单个对象
- 查询条件没有匹配的对象会抛异常:DoesNotExist
- 如果查询条件存在多个对象也会抛异常:MultipleObjectsReturned
-
First和Last
- 默认情况下可以正常从QuerySet中获取
- 隐藏bug:可能会出现first和last获取到的是相同的对象
- 解决方案:显示、手动写排序规则
count()
:返回当前查询集中的对象个数exists()
:判断查询集中是否有数据,如果有数据返回True,没有返回False-
切片
- 和python中的切片不太一样
-
QuerySet[5:10]
:获取第5条到第15条数据 - 相当于sql中的limit和offset
-
缓存集
- filter
- exlude
- all
- 都不会真正的查询数据库
- 只有我们在迭代结果集,或者获取单个对象属性的时候,它才会真正的查询数据库
- 懒查询
- 为了优化数据结构和数据的查询
-
查询条件
- 属性:
__运算符=值
- gt
- lt
- gte
- lte
- in:在某一个集合中
- contains:类似于模糊查询的like
- startswith:以什么开始,也类似于like
- endswith:以什么结束,也类似like
- exact:判断,大小写敏感,
filter(isDelete=False)
- isnull,isnotnull:判断是否为空,
filter(sname_isnall=False)
- 前面同时添加i,ignore,忽略大小写的匹配
- iexact
- icontains
- istartswith
- iendswith
- 属性:
-
Django中查询条件有时区问题
- 关闭Django中自定义的时区:√,更好用
- 在数据库中创建对应的时区表
-
F
- 可以获取我们属性的值
- 可以实现一个模型的不同属性的运算操作
- 还可以支持算术运算
-
Q
- 可以对查询条件进行封装
- 封装之后,可以支持逻辑运算:与 &、或 |、非 ~
-
模型成员
- 显性属性:
- 开发者手动书写的属性
- 隐形属性:
- 开发者没有书写,ORM自动生成的
- 如果把隐性属性手动声明了,系统就不会为你产生隐性属性了
- 显性属性:
-
模型总结
6. Template
- 标签
- 标识符:
{% %}
- 标签分为单标签和成对的标签
- 成对的标签切记不能省略,开始标签和结束标签
- 标识符:
- 结构标签
- blcok
- 块
- 用来规划我们的布局(挖坑)
- 首次出现,代表规划
- 第二次出现,代表填充以前的规划
- 第三次出现,代表填充以前的规则,默认动作是覆盖,如果不想覆盖,可以添加
{{ block.super }}
,这样就实现了增量式操作。
- extends
- 继承
- 可以获取父模板中的所有结构
- block + extends
- 化整为零
- include
- 包含
- 可以将页面作为一部分,嵌入到其他页面中
- include + block
- 由零聚一
- 三个标签也可以混合使用
- 能用block + extends搞定的,就尽量不要使用include
- 如果我们继承自一个父模板,子模板自己直接重写页面结构是不生效的,只能在既有的坑中进行填充
- blcok
- 静态资源
- 动静分离
- 创建静态文件夹
- 在settings中注册 STATICFILES_DIRS=[]
- 在模板中使用
- 先加载静态资源:
{% load static %}
- 使用
{% static 'xxx' %}
,其中xxx为相对路径
- 先加载静态资源:
- 坑点:
- 仅在debug模式中使用
- 以后需要自己单独处理
7. View
视图,用来接收Web请求,并作出响应,视图的本质就是一个Python中的函数。
-
视图的响应分未两大类:
- 以Json数据形式返回
- 以网页的形式返回:
- 重定向到另一个网页
- 错误视图(40x,50x)
-
url匹配正则注意事项:这一部分,在最新版的django(3.1.4)中,不存在这个问题
- 正则匹配时从上到下进行遍历,匹配到就不会继续向后查找了
- 匹配的正则前方不需要加反斜线
- 正则前需要加(r)表示字符串不转义
-
urls
-
路由器
- 按照列表的书写顺序进行匹配的
- 从上到下匹配,没有最优匹配的概念
-
路由规则编写:
- 我们通常直接指定以
^
开头 - 在结尾处直接添加反斜线
- 我们通常直接指定以
-
路由规则
需要注意的是:在新版本Django2.x 及以上中,url的路由表示用path和re_path代替
-
路由路径中的参数使用
()
进行获取- 一个圆括号,对应视图函数中的一个参数
- 参数:
- 路径参数:
- 位置参数:按照书写顺序进行匹配
- 关键字参数:按照参数名称匹配,和顺序就无关了
- 参数个数必须和视图函数中的参数个数一致(除了默认的request以外)
- 路径参数:
-
反向解析:
-
在
include
中添加第二个参数namespace
之后出现 **Specifying a namespace in include() without providing an app_name **的问题:解决方案 根据根路由中注册的namespace和在子路由中注册的name,这两个参数来动态获取我们的路径
在模板中使用:
{% url 'namespace:name' %}
如果带有位置参数:
{% url 'namespace:name' value1 value2 [valuen...] %}
如果带有关键字参数:
{% url 'namespace:name' key1=value1 key2=value2 [keyn=valuen] %}
-
-
-
错误页面定制
- 在模板中重写对应错误状态码的页面:
404.html
- 关闭debug
- 实现原则:就近原则
- 在模板中重写对应错误状态码的页面:
-
双R
- Request
- 内置属性
- method
- path
- GET
- 类字典结构
- 一个key允许对应多个值
- get
- getlist
- POST
- META:
- 各种客户端的元信息
- REMOTE_ADDR:远端访问IP
- 内置属性
- Response
- Request
-
知识点
内置函数:
locals()
将局部变量,使用字典的方式进行打包
key是变量名,value是变量中存储的数据
-
如果关闭调试模式可能会报错:
CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.
-
解决方案:设置任何用户均可以访问:
ALLOWED_HOSTS = ['*']
-
解决方案:设置任何用户均可以访问:
-
视图总结
8. 会话
-
爬虫
- 模拟人去请求数据
- 提取数据
- 存储数据
- 核心内容
- 数据爬取
- 数据提取
- 数据存储
- 提升效率:进程、线程、协程
- MIME:
- 作用:指定传输数据使用哪种形式打开
- 格式:大类型/小类型
- image/png
- image/jpg
-
Json
- JsonObject
- {}
- key-value
- JsonArray
- []
- 列表中可以是普通数据类型,也可以是jsonObject
- JsonObject和JsonArray可以嵌套
- 给移动端/Ajax的时候用JsonResponse
- 前后端分离
- DRF
- Google Chrome插件名:JsonFomatter、JsonView
- JsonObject
-
HttpResponse
- HttpResponseRedirect
- 重定向,暂时
- 302
- 简写 redirect
- JsonResponse
- 以Json格式返回数据
- 重写了
__init__
,序列化Json数据,指定content_type为application/json
- HttpResponsePermanentRedirect
- 重定向,永久性
- 302
- HttpResponseBadRequest
- 400
- HttpResponseNotFound
- 404
- Http404
- Exception
- raise 主动抛出异常
- HttpResponseRedirect
-
会话技术
- 出现场景
- 服务器如何识别客户端
- Http在WEB开发中基本都是短连接
- 请求的生命周期
- requetst开始
- response结束
- 种类
- cookie
- 客户端会话技术
- 数据存储在客户端
- 键值对存储
- 支持过期时间
- 默认Cookie会自动携带,本网站所有Cookie
- Cookie跨域名、跨网站
- 通过HttpResponse
- Cookie默认不支持中文
- 可以加盐(加密),获取时还需要解密
- session
- 服务端会话技术
- 数据存储在服务器中
- 默认Session存储在内存中
- Django中默认会把Session持久化到数据库中
- Django中Session的默认过期时间是14天
- 主键是字符串
- 数据是使用了数据安全
- 使用了base64
- 在前部添加了一个混淆串
- Session依赖于Cookie
- token
- 服务端会话技术
- 自定义的Session
- 如果Web页面开发中,使用起来和Session基本一致
- 如果使用在移动端或者客户端开发中,通常以Json形式传输,需要移动端自己存储Token,需要获取Token关联数据的时候,主动传递Token。
- Cookie、Session和Token对比
- cookie使用起来更简洁,服务器的压力更小;数据不是很安全
- session服务器要维护session,相对安全
- token自定义的session,拥有session的所有优点,自己维护略微麻烦,支持更多的终端
- cookie
- 出现场景
-
CSRF
- 防跨站攻击
- 防止恶意注册,确保客户端是我们自己的客户端
- 使用了cookie中的csrftoken进行验证,传输
- 服务器发送给客户端,客户端将cookie获取过来,还要进行编码转换(数据安全)
- 如何实现的
- 在我们中存在csrf_token标签的页面中,响应会自动设置一个cookie,csrftoken
- 当我们提交的时候,会自动验证csrftoken
- 验证通过,正常执行以后流程,验证不通过,直接403
-
目前状态
- MTV
- 基本完成
- Template不会再讲了
- Views也不会再讲了
- Model
- Model关系
- Model继承
- 高级
- 第三方插件
- 底层的部分原理
- AOP 面向切面编程
- 反扒
- 安全
- AOP 面向切面编程
- 文件上传
- 前后端分离
- RESTful
- 日志
- 后台管理
- 用户角色、用户权限
- 部署
- 支付宝支付
- MTV
-
算法
- 编码解码
- Base64
- urlencode
- 摘要算法、指纹算法、杂凑算法
- MD5、SHA
- MD5默认是128位的二进制
- 32位的二进制
- 32位的Unicode
- 单向不可逆的
- 不管输入多长,输出都是固定长度
- 只要输入有任意的变更,输出都会发生巨大的变化
- MD5、SHA
- 加密
- 对称加密
- 一把钥匙
- DES、AES
- 加密解密效率高
- 钥匙一旦丢失,所有数据全GG
- 非对称加密
- 两把钥匙,成对的
- 公钥和私钥
- RSA、PGP
- 安全性最高
- 算法复杂,需要时间长
- 支付宝、微信都是RSA
- 对称加密
- 编码解码
-
登录
- 首先要有一个页面
- 页面中有输入框
- 有登录按钮
- 点完登录,默认进入个人中心
- 个人中心可以显示用户名
- 首先要有一个页面
-
编码
- ASCII
- Unicode
-
Session交互图
-
会话总结
9. 迁移原理和模型关系
-
迁移
- 分两步实现
- 生成迁移文件
- 执行迁移文件
- 迁移文件的生成
- 根据models文件生成对应的迁移文件
- 根据models和已有迁移文件的差别生成新的迁移文件
- 执行迁移文件
- 先去迁移记录中查找哪些文件迁移过,哪些未迁移过
- app_label + 迁移文件名字
- 执行未迁移的文件
- 执行完毕,记录执行过的迁移文件
- 先去迁移记录中查找哪些文件迁移过,哪些未迁移过
- 重新迁移
- 删除迁移文件
- 删除迁移文件产生的表
- 删除迁移记录
- 分两步实现
-
模型关系
-
1:1
- 应用场景
- 用于复杂表的拆分
- 扩展新功能
- Django中OneToOneField
- 使用的时候,关系声明还是有细微差别
- 实现
- 使用外键实现的
- 对外键添加了唯一约束
- 数据删除
- 级联表
- 主表
- 从表
- 谁声明关系,谁就是从表
- 在开发中如何确认主从
- 当系统遭遇不可避免的毁灭时,只能保留一张表的时候,这个表就是主表
- 默认特性
- 从表数据删除,主表不受影响
- 主表数据删除,从表数据直接删除
- PROTECT受保护
- 开发中为了防止误操作,我们通常会设置此模式
- 主表如果存在级联数据,删除动作受保护,不能成功
- 主表不存在级联数据,可以删除成功
- SET
- SET_NULL:允许为NULL
- SET_DEFAULT:存在默认值
- SET():设为指定值
- 级联表
- 级联数据获取
- 主获取从,隐性属性,默认就是级联模型的名字
- 从获取主,显性属性,就是属性的名字
- 应用场景
-
1:M
- ForeignKey
- 主从获取
- 主获取从:隐性属性,级联模型_set
- student_set Manager的子类
- all
- filter
- exclude
- Manager上能使用的函数都能使用
- student_set Manager的子类
- 从获取主:显性属性
- 主获取从:隐性属性,级联模型_set
-
M:N
- 实际上最复杂
- 开发中很少直接使用多对多属性,而是自己维护多对多
- 产生表的时候会产生单独的关系表
- 关系表中存储关联表的主键,通过多个外键实现的
- 多个外键值不能同时相等
- 级联数据获取
- 从获取主
- 使用属性,属性是一个Manager子类
- 主获取从
- 隐性属性
- 也是Manager子类,操作和从操作主完全一样
- 隐性属性
- 从获取主
- 级联数据
- add
- remove
- clear
- set
-
ManyRelatedManager
- 函数中定义的类
- 并且父类是一个参数
- 动态创建
-
模型继承
- Django中模型支持继承
- 默认继承是会将通用字段放到父表中,特定字段放在自己的表中,中间使用外键连接
- 关系型数据库,关系越复杂,效率越低,查询越慢
- 父类表中也会存储过多的数据
- 使用元信息来解决这个问题
- 使模型抽象化
- 抽象的模型就不会在数据库中产生映射了
- 子模型映射的表中直接包含父模型的字段
-
在企业开发中
-
model -> sql
- 都可以使用
-
sql -> model
django也提供了很好的支持
-
python manage.py inspectdb
- 可以直接根据表生成模型
- 元信息中包含一个属性
managed=False
如果自己的模型不想被迁移系统管理,也可以使用
managed=False
进行声明
-
-
10. 静态资源
html中的img属性:
<img src="{{ icon_url }}" alt="{{ username }}">
,alt 属性是一个必需的属性,它规定在图像无法显示时的替代文本。-
在models中设置文件上传的保存路径:
-
在settings中设置media路径:
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')
-
在models中设置属性:
u_icon = models.ImageField(upload_to='%Y/%m/%d/icons')
可以通过增加时间标记进行分文件夹保存
-
-
MCS结构体系,multi client server
-
model、静态资源、文件上传、requests总结
11. 缓存
-
缓存,Django Cache
- 提升服务器响应速度
- 将执行过的操作数据存储下来,在一定时间内,再次获取数据的时候,直接从缓存中获取
- 比较理想的方案,缓存使用内存级缓存
- Django内置缓存框架
-
缓存框架的核心目标
- 较少的代码
- 缓存应该尽可能快
- 因此围绕缓存后端的所有框架代码应该保存在绝对最小值,特别是对于获取操作
- 一致性
- 缓存API应该是提供跨越不同缓存后端的一致接口
- 可扩展性
- 基于开发人员的需求,缓存API应该可以在应用程序级别扩展
- 较少的代码
-
缓存
Django中内置了缓存框架,并提供了几种常用的缓存
- 基于Memcached缓存
- 使用数据库进行缓存
- 使用文件系统进行缓存
- 使用本地内存进行缓存
- 提供缓存扩展接口
-
缓存配置
在views前面新增装饰器:
@cache_page(30)
,括号中的时间为缓存保留的时间(秒)-
缓存数据流程图
-
如果不用装饰器,也可以通过set和get缓存的方式,进行手动写入和获取缓存
# @cache_page(30) def news(request): result = cache.get("news") # 如果缓存中能找到news对应的值,直接返回该值 if result: return HttpResponse(result) news_list = [] for i in range(10): news_list.append("最近贸易战又开始了 %d" % i) sleep(5) data = { 'news_list': news_list } # 如果缓存中没有找到news的值,则返回response,并将内容写入到缓存中 response = render(request, 'news.html', context=data) cache.set('news', response.content, timeout=60) return response
-
redis:内存级的数据库,django中没有redis的缓存实现,所以需要pypi安装
pip install django-redis
pip install django-redis-cache
-
redis在windows中启动的方法
-
修改缓存为redis
CACHES = { 'default': { # django原生缓存 # 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', # 'LOCATION': 'my_cache_table', # 'TIMEOUT': 60 * 5, # redis缓存 "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } }
-
查看redis缓存的数据
-
查看过期时间
-
配置不同的数据库,选择不同的数据库进行缓存
-
配置
CACHES = { 'default': { # django原生缓存 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 'LOCATION': 'my_cache_table', 'TIMEOUT': 60 * 5, }, 'redis_backend': { # redis缓存 "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", }, } }
-
选择
@cache_page(60, cache='redis_backend')
-
12. 中间件和AOP
中间件:是一个轻量级的、底层插件。可以介入Django的请求和相应过程(面向切面编程)。中间件的本质是一个python类,装饰器。
AOP:面像切面编程,Aspect Oriented Programming。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理步骤中的某个过程或阶段,以获得逻辑过程中各个部分之间低耦合的隔离效果。
-
中间件可以切入的点
-
切入函数
-
自定义中间件
-
AOP中间件的作用
-
实现统计功能
- 统计IP
- 统计浏览器
-
实现权重控制
- 黑名单
- 白名单
-
实现反爬
-
反爬虫
十秒之内只能查询一次
-
频率请求限制反爬
实现频率控制
-
-
通过中间件的
process_exception
函数实现 界面友好化、应用交互友好化访问中出错、出异常后跳转到首页
-
HTTP默认端口为80,HTTPs默认端口为443
-
csrf问题验证失败解决方法
- 注释设置中的csrf中间件
- 在页面的POSThtml代码中,添加
{% csrf_token %}
- 在views视图函数中添加csrf豁免装饰器:
csrf_exempt
-
中间件调用顺序
- 中间件注册的时候是一个列表
- 如果我们没有在切点出直接进行返回,中间件会依次执行
- 如果我们直接进行了返回,后续中间就不再执行了
-
切点
- process_request
- process_view
- process_template_response
- process_response
- process_exception
切面
13. 分页器
-
分页器原理
-
分页显示:
Paginator
def get_students_with_page(request): page = int(request.GET.get("page", 1)) per_page = int(request.GET.get("per_page", 10)) students = Student.objects.all() paginator = Paginator(students, per_page) page_obj = paginator.page(page) data = { "page_object": page_obj } return render(request, 'students_with_page.html', context=data)
@property
:将函数设为类的私有属性,我们可以观测它。-
验证码
def get_code(request): # 初始化画布,初始化画笔 mode = 'RGB' size = (200, 100) red = get_color() green = get_color() blue = get_color() color_bg = (red, green, blue) image = Image.new(mode=mode, size=size, color=color_bg) imagedraw = ImageDraw(image, mode=mode) imagefont = ImageFont.truetype(settings.FONT_PATH, 100) verify_code = generate_code() request.session['verify_code'] = verify_code for i in range(len(verify_code)): fill = (get_color(), get_color(), get_color()) imagedraw.text(xy=(50 * i, 0), text=verify_code[i], font=imagefont, fill=fill) for i in range(10000): fill = (get_color(), get_color(), get_color()) xy = (random.randrange(201), random.randrange(100)) imagedraw.point(xy=xy, fill=fill) fp = BytesIO() image.save(fp, "png") return HttpResponse(fp.getvalue(), content_type="image/png")
-
富文本
- 带格式的文字:
- 博客、论坛
- 富文本:RTF
- MarkDown
- 博客、论坛
- 安装插件:
django-tinymce
(2.7.0)
- 带格式的文字:
-
总结
14. AXF项目
14.1 需求分析
-
技术部
- 产品经历
- 产品狗
- 一条产品线两个产品
- 产品PRD(Product Requirement Document)产品需求文档
- 原型图(其实就和真实网站长的差不多,只不过页面都是静态的,假的)
- 后端
- 后端基本都是人最多的
- 最少2人
- Python
- Java
- PHP
- Node.js
- Go
- 根据需求进行表结构设计
- 有哪些表
- 表中有哪些字段
- 表有哪些关系
- UI
- UD:界面设计
- UE:用户体验
- 前端
- MTV
- HTML5 Web前端 一个人
- REACTNATIVE
- Android
- IOS
- 测试
- 黑盒测试
- 功能测试
- 点点测试(Excel,check_list)
- 白盒测试
- 不会正向开发,可以写代码测试你的代码
- 高级开发,专门用来查找bug
- 黑盒测试
- 运维
- 上线
- 维护稳定运转
- 版本迭代
- 产品
- 产品经历
-
AXF项目分析
- 主页面显示
- 最简单的,数据查询,显示
- 商品数据展示
- 级联查询,排序
- 用户系统
- 核心系统
- 购物车系统
- 商品和用户的关系
- 订单系统
- 购物车数据转换成订单
- 支付系统
- 接口调用
- 扩展
- 地址管理系统
- 积分系统
- 会员级别
- 评价系统
- 优惠券系统
- 数据安全
- 过滤器
- 反爬
- 权限:用户角色
- 部署
- 动静分离部署
- 主页面显示
-
开始开发
- 基本工程搭建
- 前端静态搭建
- Model -> DB
- 业务逻辑开发
- 前后端一起来
- ajax
-
前端基础架构
-
base模板
- 导入通用资源
- reset.css,自己找的地址
- 导入通用资源
-
viewpoint:将html从windows适配到手机
-
前端适配
- 推荐百分比,而不推荐固定尺寸
- 适配单位
- px:像素
- em:
- 相对单位
- 默认相对于父级元素
- 默认大小 1em = 16px
- rem
- 相对单位
- 相对于根基元素(root)
- 默认大小 1rem = 16px
- 所有图形界面,底层计算都是px
- 弹性盒模型
- 响应式布局
-
项目中
- 屏幕宽度的十分之一作为rem的基础单位
-
-
数据展示
- 建立数据
- 先建表
- Model -> SQL
- 插入数据
- 数据查询
- 建立数据
-
程序调试
- 打印日志
- log
- logging
- debug
- 断电调试
- 解决稳定复现bug的好方案
- 统计工具
- DjangoDebugToolbar
- Django调试工具条
- 拥有极强的调试功能
- 提供了各种信息的获取
- DjangoDebugToolbar
- 打印日志
-
项目
- 端的概念
- 京东自营
- 用户端
- 后台管理端
- 第三方卖家
- 用户端
- 商家端
- 后台管理端
- 淘宝
- 用户端
- BS/CS
- MCS
- 商家端
- BS/CS
- 后台管理端
- BS/CS
- 用户端
- 京东自营
- AXF
- 用户端
- MTV
- 前后端都需要我们自己搞定
- MTV
- 糅合之前学过的知识点
- 写地址的时候,记得把地址写全了,比如说最后面的
/
,如果不写的话,会多一次重定向
- 用户端
- 前后端分离
- 后端RESTApi
- JSON传输数据
- 前端
- VUE
- Android
- IOS
- 后端RESTApi
- 端的概念
-
需求,统计用户
- 自己统计
- 通过中间件直接实现
- 使用专用的统计分析工具
- 百度统计
- 极光统计
- 友盟统计
- 自己统计
14.2 一些开发时遇到的问题
-
pymysql 报错:from . import connections # noqa: E402
这里需要下载 0.10.1的pymysql,不然会报错
-
mysqlclient 1.4.0 or newer is required; you have 0.10.1
需要在
__init__
文件下加如下内容import pymysql pymysql.version_info = (1, 4, 13, "final", 0) pymysql.install_as_MySQLdb()
-
pycharm 高亮提示 unresolved template reference的解决
需要设置django的settings.py的位置
-
安装 django-debug-toolbar的时候,不要直接
pip install
,否则会直接卸载了你低版本的django,给你装一个高级的,然后运行就会报错了所以需要安装指定版本的:
pip install django-debug-toolbar==1.10.1
14.3 一些需要注意的细节
- 链接路径后面无特殊要求,一定要加
/
(可以少一步请求) - js获取jquery对象属性
- attr:可以获取任意属性
- prop:只能获取内置属性
- 项目中多块逻辑拥有相同操作
- 封装一个函数
- 装饰器
- 中间件
- 浏览器行为
- 重定向
- 跨域
- 价钱后端必算,前端选算
- PUT和PATCH
- PUT的时候需要提供所有字段,带有默认值的字段不提供也不会报错(最好还是提供)
- PATCH修改对象的部分字段
14.4 Note
-
User
- 用户表设计
- username
- password
- phone
- icon
- is_active
- is_delete
- 用户表设计
-
高级密码安全工具
- 不再使用单一的算法实现
- 至少使用两种以上的算法
- 算法中融入时间散列
- 将输入数据进行哈希处理
- 哈希处理之后拼接时间戳
- 中建使用特定拼接符号
- 将拼好的数据进行编码
- 验证策略
- 将输入进行相同的哈希策略
- 将数据库中的密码进行解码处理
- 去除时间散列的混淆
- 比较哈希码
- 不再使用单一的算法实现
-
版本升级后,策略不兼容
- 第一版本,注册之后,密码是明文
- 第二版本,注册之后,密码是hash值
- 第三版本,注册之后,密码是hash + 时间散列
- 假定目前处于第三版本,让你同时兼容第一第二版本
- 对请求的参数添加版本号,没添加的就是旧版本
- 对于低版本使用特定认证,认证完后,在会话中将低版本的版本号存下来
- 小米低版本兼容
- 除了密码外,又加了短信验证码验证
-
homework
- 邮箱校验
- 密码一致性校验
- 自己封装一个高级密码安全工具
-
用户激活,认证
- 途径
- 邮件
- 短信
- 人工审核
- 邮件
- 发送邮件
- 收件人地址
- 发件人的信息
- 用户名
- 密码
- 服务器
- 邮件服务器
- 端口
- 内容
- 点击邮件中的链接就可以激活
- 链接中存在用户的唯一标识
- http://xxxxx/activate/?u_token=YYY
- u_token 缓存中作为key,value -> user_id
- u_token -> uuid
- 标识存在过期时间
- 标识存在使用次数限制
- 链接中存在用户的唯一标识
- 发送邮件
- 途径
-
错误信息
- 先将错误信息存储下来
- 在错误显示页面获取错误信息
- 保证错误信息只能出现一次
- 获取到数据之后,直接将自己删除
-
购物车
-
购物多对多的关系
- 用户
- 商品
-
订单
- 订单和已购买商品是一对多的关系
- 表关系
- 订单表
- 属于哪个用户
- 订单商品表
- 购物车里
- 地址
- 每个订单对应一个地址
- 一个地址可以对应多个订单
- 订单会级联收获地址表,而不是人的地址表
- 优惠券
- 订单表
-
购物车设计
-
购物车逻辑
-
-
添加购物车
- 需要用户
- 如果用户未登录,直接跳转登录
- 需要商品
- 传第商品唯一标识
- 添加的合法性验证
- 此数据不存在,创建购物车数据
- 此数据存在,直接将数量+1
- 需要用户
-
全选逻辑
- 默认状态
- 全选按钮是选中
- 内部所有商品是选中的
- 全选按钮未选中
- 内部商品只要存在未选中的,全选就应该是未选中
- 全选按钮是选中
- 点击全选
- 原状态是选中
- 全选和所有商品都变成未选中
- 原状态是未选中
- 全选和所有商品都变成选中
- 原状态是选中
- 点击单个商品
- 商品由选中变成未选中
- 全选一定变成未选中
- 商品由未选中变成选中
- 全选的默认状态就是未选中
- 可能变成选中
- 商品由选中变成未选中
- 默认状态
-
支付
- 官方文档
- 常见的支付
- 支付宝
- 企业资质
- 营业执照
- 微信
- 要求同支付宝
- 要认证,一次200,一年一收
- 银联
- 百度钱包
- 京东钱包
- 支付宝
- 支付宝支付
- 支付宝开放平台
- 蚂蚁金服开放平台
-
部署
- 默认Django中使用的是开发者服务器
- runserver
- 路由处理功能,动态资源处理
- 如果是debug的话,静态资源处理功能
- 功能健壮,性能比较低,仅适用于开发
- runserver
- 部署不会使用单一服务器
- Apache
- Nginx
- HTTP服务器
- 处理静态资源
- 反向代理
- uWSGI:HTTP服务器
- gunicorn:HTTP服务器
- 邮件服务器
- 流媒体服务器
- HTTP服务器
- 默认Django中使用的是开发者服务器
-
部署云服务器
从零开始做的
-
安装云服务器系统
- Ubuntu 16.04
-
安装一套开发环境
- Python
- 2.x
- 3.x
- pip
- 注意版本兼容
- virtualenv
- 版本不兼容
- workon_home
- source xxx
- mysql
- apt 直接安装
- redis
- 源码安装
- make & make test
- utils/install_server.sh
- nginx
- 添加钥匙
- 添加源
- update,install
- 准备进行部署
- 安装项目所需的依赖
- pip install -r xxx.txt
- 修改配置文件的指定路径
- 从静态文件开始部署
- 动态资源
- 处理好数据库
- 创建库,创建表
- 插入数据
- 安装项目所需的依赖
- 坑点
- 邮件发送
- 25端口是非安全端口,阿里不允许使用
- 使用安全协议接口:SSL端口,465/994
- 邮件发送
- Python
-
ab测试
-
ab安装:
sudo apt-get install apache2-utils
-
测试100次
ab -n 100 http://127.0.0.1/axf/mine/
-
-
通过配置pycharm实现远程写代码
-
总结
14.5 Nginx
-
Nginx简介
-
HTTP和反向代理
-
Nginx配置文件
- 指令分未简单指令和块指令
- 一个简单指令:由名称和参数组成,以空格分隔,并以分号结尾
- 一个块指令:和简单指令具有相同的结构,但不是以分号结束,而是以一个大括号包围的一堆附加指令结束
- 如果一个大括号内可以由其他的指令,它接被称为一个上下文,比如(events,http,server,location)
-
Nginx配置文件结构
-
main:
-
events:
-
http
-
server
-
location
-
Django部署
-
nginx配置文件(关于AXF项目)
#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } http { include D:/nginx-1.20.1/conf/mime.types; default_type application/octet-stream; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; server { listen 80; server_name localhost; root E:/1-Work/3-Code/python_projects/6-AXFProject/GPAXF; #charset koi8-r; #access_log logs/host.access.log main; location /static { alias E:/1-Work/3-Code/python_projects/6-AXFProject/GPAXF/static; # root html; # index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } } 折叠
-
nginx配置文件测试
-
启动nginx
-
win10
nginx -c E:/1-Work/3-Code/python_projects/6-AXFProject/GPAXF/config_win10.conf
-
ubuntu
nginx -c /mnt/e/1-Work/3-Code/python_projects/6-AXFProject/GPAXF/config_ubuntu.conf
-
-
安装uwsgi报错
这是因为uwsgiconfig.py文件中,os.uname()是不支持windows系统的,platform模块是支持任何系统
-
修改uwsgiconfig.py中的所有os.uname,将其改为platform.uname,在文件顶部添加import platform
经检测,uwsgi里面的.h中的库都是linux的,windows没办法
拉倒吧
uwsgi启动:
/home/litian/.pyenv/versions/3.5.4/bin/uwsgi --ini uwsgi.ini
-
启动总结:
-
进入nginx目录:
nginx -c /mnt/e/1-Work/3-Code/python_projects/6-AXFProject/GPAXF/config_ubuntu.conf
-
进入工程目录:
/home/litian/.pyenv/versions/3.5.4/bin/uwsgi --ini uwsgi.ini
-
-
redis安装遇到问题:
it seems like you don't have a redis executable. Did you run make install yet?
这是因为没有加入自己的
src/redis-server
-
安装成功
-
redis-cli成功
-
测试项目的conf是不是正确的
-
启动
-
切到项目路径
cd /mnt/e/1-Work/3-Code/python_projects/6-AXFProject/GPAXF
-
启动mysql
sudo service mysql start
-
启动nginx
sudo /usr/sbin/nginx -c /mnt/e/1-Work/3-Code/python_projects/6-AXFProject/GPAXF/config_ubuntu.conf
停止
sudo /usr/sbin/nginx -s stop
-
启动uwsgi
sudo /home/litian/.pyenv/versions/3.5.4/bin/uwsgi --ini uwsgi.ini
停止
sudo /home/litian/.pyenv/versions/3.5.4/bin/uwsgi --stop uwsgi.pid
-
-
反向代理
-
ngnix也可以对接runserver
# runserver location / { proxy_pass http://127.0.0.1:9000; } # uwsgi # location / { # include /etc/nginx/uwsgi_params; # uwsgi_pass 0.0.0.0:8888; # }
-
负载均衡模块:upstream
-
负载均衡是分发请求的
-
配置
-
14.6 Gunicorn
安装:
pip install gunicorn
-
配置:
# runserver location / { proxy_pass http://127.0.0.1:9000; }
- 这里的端口要与gunicorn 的端口一致
-
启动gunicorn:
gunicorn -b 0.0.0.0:9000 GPAXF.wsgi
- 指定启动地址:
-b
- 指定启动地址:
启动nginx:
sudo nginx -c /mnt/e/1-Work/3-Code/python_projects/6-AXFProject/GPAXF/config_ubuntu.conf
重载nginx:
sudo nginx reload
启动runserver:
python3.5 manage.py runserver 9000
15. RESTful
RESTful:Representational State Transfer,(资源的)表现层状态转化
URI只代表资源的实体,不代表它的形式
-
到底什么是RESTful框架
- 每一个URI代表一种资源
- 客户端和服务器之间,传递这种资源的某种表现层
- 客户端通过4个HTTP动词,对服务端资源进行操作,实现“表现层状态转换”
-
HTTP常用动词
-
好的程序:高内聚,低耦合
- 高内聚:针对于一类事物的操作,封装在一块
过滤信息:如果记录数量过多,服务器不可能将它们返回给用户,API因该提供参数,过滤返回结果
-
状态码:服务器向用户返回的状态码和提示信息,常见的有以下一些:
-
RESTful API最好做到Hypermedia,即返回结果中提供链接,链向其他API方法,使得用户不查文档,也知道下一步应该做什么
服务器返回的数据格式,应该尽量使用JSON
API的身份认证应该使用OAuth2.0框架
-
tips
- 如果不对应用在settings中进行注册的话,不影响访问url,但是在models中建立的模型无法被makemigrations识别
-
问题:
-
这里进行post测试之后返回的值总是500
看了下发现是
request.POST.get
没有获取到对应的参数-
解决方案:看这个链接的评论席中
-
在使用
httpie
进行操作的时候,又要换成如下代码了,我自己猜测的话,前者参数是因为放在了url链接后面,后者httpie是放在body中,所以对于django,两种获取参数的方式得不一样# post = QueryDict(request.get_full_path().split('?')[1]) post = request.POST b_name = post.get('b_name') b_price = post.get('b_price')
-
-
视图函数
- FBV
- Function Base View
- CBV
- CLass Base View
- FBV
-
类视图
- CBV
- 继承自View
- 注册的时候使用的
as_view()
- 入口
- 不能使用请求方法的名字作为参数的名字
- 只能接收已经存在的属性对应的参数
- 定义了一个view
- 创建了一个类视图对象
- 保留,拷贝传递进来的属性和参数
- 调用dispatch方法
- 分发
- 如果请求方法在我们的允许的列表中
- 从自己这个对象中获取请求方法名字小写对应的属性,如果没有找到,会给一个默认:
http_method_not_allowed
- 从自己这个对象中获取请求方法名字小写对应的属性,如果没有找到,会给一个默认:
- 如果请求方法不在我们允许的列表中,直接就是
http_method_not_allowed
- 之后,将参数传递,调用函数
- 默认实现了options方法
- 获取接口信息,可以获取接口都允许什么请求
- 简化版的流程
- as_view
- dispatch
- 调用实现请求方法对应的函数名
- TemplateView
- 多继承的子类
- VIew:
- 分发
- 函数 dispatch
- ContextMixin:
- 接受上下文
- 从视图函数传递到模板的内容
- 函数get_context_data
- TemplateResponseMixin
- 将内容渲染到模板中
- template_name
- template_engine
- response_class
- content_type
- 函数 render_to_response
- ListView
- MultipleObjectTemplateResponseMixin
- TemplateResponseMixin
- 获取模板名字
- 首先根据template_name
- 如果没找到
- 自己根据应用的名字,关联模型的名字,
_list.html
去查找 - App/book_list.html
- 自己根据应用的名字,关联模型的名字,
- BaseListView
- MultipleOBjectMixin
- ContextMixin
- get_queryset:获取查询结果集
- View
- 默认实现了get,渲染成了response
- MultipleOBjectMixin
- MultipleObjectTemplateResponseMixin
- DetailView
- SingleObjectTemplateResponseMixin
- TemplateResponseMixin
- 重写了获取模板名字的方法
- BaseDetailView
- View
- SingleObjectMixin
- ContextMixin
- SingleObjectTemplateResponseMixin
-
虚拟环境
- virtualenvwrapper:
- 对virtualenv的包装
- mkvirtualenv
- rmvirtualenv
- workon
- deactivate
- virtualenv
- virtualenv
- source /xx/xx/activate
- deactivate
- rm -rf xxx
- 指令在哪调用,虚拟环境就在哪生成
- virtualenvwrapper:
-
重量级RESTful
- django-rest-framework
- REST难点
- 模型序列化
- 正向序列化:将模型转换成JSON
- 反向序列化:将JSON转换成模型
- serialization
- 在模块serializers
- HyperLinkedModelSerializer
- 序列化模型,并添加超链接
- Serializer
- 手动序列化
- HyperLinkedModelSerializer
- 在模块serializers
- 双R
- Request
- rest_framework.request
- 将Django中的Request作为了自己的一个属性
_request
- 属性和方法:
- content_type
- stream
- query_params (实际上就是直接获取GET参数,
_request.GET
) - data:同时兼容POST、PUT、PATCH
- user:
- 可以直接在请求上获取用户
- 相当于在请求上添加一个属性,用户对象
- auth:
- 认证
- 相当于在请求上添加了一个属性,属性的值就是token
- successfulauthenticator:认证成功
- Response
- 依然是HttpResponse的子类
- 自己封装的
- data可以直接接受字典,并转为json
- status 可以直接指定状态码
- 属性
- rendered_content
- status_text
- Request
- APIView
- renderer_classes:渲染的类
- parser_classes:解析转换的类
- authentication_classes:认证的类
- throttle_classes:节流的类,控制请求频率的
- permission_classes:权限的类
- content_negotiate_class:内容过滤的类
- metadata_class:元信息的类
- versioning_class:版本控制的类
- as_view:()
- 调用父类中的
as_view()
-> dispatch - dispatch 被重写了
-
initialize_request()
:使用django的request构建了一个REST中的Request
- 调用父类中的
- initial
- perform_authentication:
- 执行用户认证
- 遍历了我们的用户认证器
- 如果认证成功,返回一个元组
- 元组中的第一个元素就是 user
- 第二个元素就是 auth,也叫token
- check_permissons:
- 检查权限
- 遍历权限检测器
- 只要有一个权限不能验证通过
- 就直接显示权限被拒绝
- 当所有权限都满足,才算是拥有权限
- check_throttles:
- 检测频率
- 遍历频率限制器
- 如果验证不同,就需要等待
- perform_authentication:
- csrf_exempt
- 所有APIView的子类都是csrf豁免的
- 错误码
- 封装在status模块中
- 实际上就是一个个常量类
- 针对视图函数的包装
- CBV:APIView
- FBV:
- 添加
@api_view
的装饰器 - 必须手动指定允许的请求方法
- 添加
- 模型序列化
-
Bug
- 将request内容转换为JSON数据出现bug
-
REST-Framework
- 序列化器:serializers
-
HelloREST
- 序列化器
- 视图函数
- viewsets.ModelViewSet
- CBV
- 视图集合
- 路由
- routers.DefaultRouter
- 记得在installed_apps添加 rest_framework
- runserver
- 所有api变成可视化
- 超链接
- HyperLinkedModelSerializer
- 对数据集合实现了
- 路由 /users/ /groups/
- get
- post
- 对单个实现了
- 路由 /users/id/ /groups/id/
- get
- post
- delete
- patch
- viewsets 做了视图函数的实现
- router 做了路由的注册
-
命名规范
- 拒绝 中文、空格、特殊字符、关键字、保留字在命名和路径中
- 拒绝 数字开头、拒绝
$
开头 - 小写字母或大写字母开头,驼峰命名
- 使用框架,注意远离框架的名字
-
Admin
- django内置后台管理
- User和Group
- 自带权限
-
小结
15.1 APIView
- 子类
- generic包中
- GenericAPIView
- 增加模型的获取操作
- get_queryset
- get_object
- lookup_field:默认是主键
- get_serializer
- get_serializer_class
- get_serializer_context
- filter_queryset
- paginator
- paginate_queryset
- get_paginated_response
- CreateAPIView
- 创建的类视图
- 继承GenerateAPIView、CreateModelMixin
- 实现了POST进行创建
- ListAPIView
- 列表的类视图
- 继承GenerateAPIView、ListModelMixin
- RetrieveAPIView
- 查询单个数据的类视图
- 继承GenerateAPIView、RetrieveModelMixin
- 实现了get
- DestroyAPIView
- 销毁、删除数据的类视图
- 继承GenerateAPIView、DestroyModelMixin
- 实现了delete
- UpdateAPIView
- 更新数据的类视图
- 继承GenerateAPIView、UpdateModelMixin
- 实现了put和patch
- ListCreateAPIView
- 获取列表数据
- 创建数据的类视图
- 继承GenerateAPIView、ListModelMixin、CreateModelMixin
- 实现了get、post
- RetrieveUpdateAPIView
- 获取单个对象、更新单个对象的类视图
- 继承GenerateAPIView、RetrieveModelMixin、UpdateModelMixin
- 实现了get、put、patch
- RetrieveDestroyAPIView
- 获取、删除单个数据的类视图
- 继承GenerateAPIView、RetrieveModelMixin、DestroyModelMixin
- 实现了get、delete
- RetrieveUpdateDestroyAPIView
- 获取、更新、删除单个数据的类视图
- 继承GenerateAPIView、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin
- 实现了get、put、delete
- GenericAPIView
- mixins
- CreateModelMixin
- create
- perform_create
- get_success_header
- ListModelMixin
- list
- 查询结果集
- 添加分页功能
- 序列化
- list
- RetrieveModelMixin
- retrieve
- 获取单个对象,并序列化
- retrieve
- DestroyModelMixin
- destroy
- 获取单个对象
- 调用执行删除
- 返回 Response 状态码 204
- perform_destroy
- 默认是模型的delete
- 如果是数据的逻辑删除
- 重写进行保存
- destroy
- UpdateModelMixin
- update
- 获取对象,进行合法验证
- 执行更新
- perform_update
- partical_update
- 差量更新,对应的就是patch
- update
- CreateModelMixin
- viewsets
- ViewSetMixin
- 重写了as_view
- GenericViewset
- 继承GenericAPIView、ViewSetMixin
- ViewSet
- 继承APIView、ViewSetMixin
- 默认啥都不支持,需要自己手动实现
- ReadOnlyViewSet
- 只读的模型视图集合
- 继承RetrieveModelMixin、ListModelMixin、GenericViewSet
- ModelViewSet
- 直接封装对象的所有操作
- 继承GenericViewSet、CreateModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin、ListModelMixin
- ViewSetMixin
- generic包中
15.2 用户模块
-
用户注册
- RESTful
- 数据开始
- 模型,数据库
- 创建用户
- 用户身份
- 管理员用户
- 普通用户
- 删除用户
- 用户身份
- 注册实现
- 添加了超级管理员生成
-
用户登录
- 验证用户名密码
- 生成用户令牌
- 出现了和注册共用post冲突
- 添加action
- path/?action=login
- path/?action=register
- 异常捕获尽量精确
-
用户认证
- BaseAuthentication:authenticate
- 认证成功会返回一个元组
- 第一个元素是user
- 第二个元素是token、auth
- 认证成功会返回一个元组
- BaseAuthentication:authenticate
-
用户权限
- BasePermission:has_permission
- 是否具有权限
- true:拥有权限
- false:未拥有权限
- BasePermission:has_permission
-
用户认证和权限
- 直接配置在视图函数上就ok了
-
小结
15.3 用户注册
- 需求
- 存在级联数据
- 用户和收货地址
- 节流
- 分析
- 数据开始
- 模型定义
- 用户和地址:一对多
- 用户表
- 地址表
- ForeignKey
- 序列化
- 级联数据如何实现序列化
- 节流
- 数据开始
15.4 节流器
- BaseThrottle
- allow_request:是否允许的核心
- get_ident:获取客户端唯一标识
- wait:等待多长时间,等待函数
- SimpleRateThrottle
- get_cache_key:获取缓存的标识
- get_rate:获取频率
- parse_rate:转换频率,num/duration
- duration:s、m、h、d
- allow_request:是否允许请求,重写的方法
- throttle_success:允许请求,进行请求记录
- throttle_failure:请求失败,不允许请求
- wait:还有多少时间允许
- AnonRateThrottle
- get_cache_key:获取缓存key的原则
- UserRateThrottle
- 和上面一模一样
- ScopedRateThrottle
- 和上面的一样
- 多写了从属性中获取频率
15.6 RESTful总结
- django-rest-framework
- serializers
- 序列化工具:序列化与反序列化
- 级联模型
- 添加级联字段
- nested
- 级联字段的key必须就是原来存在的
- 隐形属性
- 自定义related_name
- APIView
- CBV,类视图
- 实现各种请求的处理
- mixins
- CRUDL
- 对模型操作
- viewsets
- 对APIView和Mixins的高度封装
- 可以对接router
- router
- DefaultRouter
- 可以直接批量注册路由
- authentication
- APIView中会自动认证
- 自己创建认证类,实现认证方法
- 认证成功返回元组,用户和令牌
- permission
- 添加权限控制
- 用户所拥有的权限
- throttle
- 节流
- 控制访问频率
- serializers
16. Celery
-
消息队列
- 异步任务
- 定时任务
-
需要了解的知识
- 选择并安装消息容器(载体)
- 安装Celery并创建爱你第一个任务
- 开启工作进程,并调用任务
- 记录工作状态和返回的结果
-
Log级别
- info
- debug
- warning
- error
- critical
-
端
- 用户端
- 公司自己的后台
- 商家端
-
后台管理
- 快速实现自己的后台
- 内置了一个admin
- 也有第三方的:
- xadmin
- suit
-
Django内置模型
- 用户
- 组
-
小结
90. 技能点
- HTTP_X_FORWARDED_FOR
- 获取你的原始IP
- 通过普通的代理发送请求
- 如果获取REMOTE_ADDR获取到的是代理IP
- 获取你的原始IP
- 代理:
- 普通代理
- 高匿代理
- 效率越低,请求速度越慢
本文由mdnice多平台发布