Django-Part5
Django-Part5——数据交互
[TOC]
前后端交互
发送请求的方式
- 浏览器地址栏直接输入url回车 (GET)
- a标签href属性 (GET)
- form表单 (GET/POST)
- ajax (GET/POST)
Ajax
简介
Ajax 最大的优点是异步提交,局部刷新。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
Ajax 在这里只学习jQuery封装之后的版本,而不是原生的。所以在前端页面使用ajax的时候需要确保导入了jQuery。
并不只有jQuery能够实现ajax,其他的框架也可以,原理是一样的。
demo:
1 |
|
1 | def ab_ajax(request): |
- 针对后端如果是用HttpResponse返回的数据,回调函数不会自动反序列化
- 解决方式1:在前端JSON.parse()
- 解决方式2:在ajax里面配置一个参数
- 如果后端直接用的是JsonResponse返回的数据,回调函数会自动反序列化
编码格式(Content-Type)
前后端传输数据的编码格式:
- urlencoded(例如:username=jason&password=123)
- formdata
- json
- ……
在form表单中:
- 默认的数据编码格式是urlencoded,推荐都写成formdata。
- django针对符合urlencoded编码格式的数据都解析封装到request.POST中。
- 编码格式设定为formdata时,普通的键值对还是解析到request.POST中,文件将解析到request.FILES中(文件在urlencoded格式下只会解析文件名)。
- form表单是没有办法发送json格式数据的。
Ajax:
- 默认的编码格式也是urlencoded
- 对符合urlencoded编码格式的数据都解析封装到request.POST中
Ajax发送json
前后端传输数据的时候一定要确保编码格式跟数据真正的格式是一致的。
ajax传输json格式数据注意点:
- contentType参数指定成:application/json
- 数据是原始的json格式数据
- django后端不会封装处理json格式数据,需要自己在request.body获取二进制数据并处理
1 | <script> |
- request.is_ajax():判断当前请求是否是ajax请求,返回布尔值
- request.body:获取请求体,这里是未经处理的二进制数据
- 处理json文件:json.loads(request.body)
1 | def ab_ajax(request): |
Ajax发送文件
- ajax发送文件需要借助于js内置对象FormData
- 需要指定两个关键性的参数 contentType:false processData:false
- django能直接识别formdata对象,并将内部的普通键值对自动解析封装到request.POST中,文件数据自动解析封装到request.FILES中
1 | <script> |
1 | def ab_file(request): |
Django自带的序列化组件
- 使用
django.core.serializers.serialize('指定数据格式', 数据本体)
快速完成序列化 - 后续还有更多的序列化组件,例如:drf
1 | # 需求:在前端获取后端用户表里面所有的数据,列表套字典 |
Ajax结合SweetAlert
- 每个元素都可以自定义属性,可以用来传值
1 | <script> |
forms组件
forms组件能够完成的事情:
- 渲染html代码
- 校验数据
- 展示提示信息
数据校验前端可有可无,但是后端必须要有!
因为前端的校验是弱不禁风的,可以直接修改,或者利用爬虫绕过前端页面直接朝后端提交数据。
定义forms组件
1 | from django import forms |
校验数据
- 可以直接在 python console 中测试
- 默认情况下数据可以多传但是绝不可能少传
1 | from app01 import views |
渲染标签
- forms组件只会自动渲染获取用户输入的标签(input select radio checkbox),不能渲染提交按钮
- 设置form表单让浏览器不做校验
<form action="" method="post" novalidate>
1 | def index(request): |
1 | <p>第一种渲染方式:代码书写极少,封装程度太高,不便于后续的扩展,一般情况下只在本地测试使用</p> |
自定义错误信息
1 | class MyForm(forms.Form): |
钩子函数(HOOK)
- 钩子函数将书写在Form类中,能够让我们自定义校验规则
- 在forms组件中有两类钩子
- 局部钩子:给单个字段增加校验规则
- 全局钩子:给多个字段增加校验规则
1 | class MyForm(forms.Form): |
forms字段其他参数与样式渲染
- label:字段名
- error_messages:自定义报错信息
- initial:默认值
- required:控制字段是否必填
- widget:type类型
- attrs:以字典类型定义属性
- validators:可以使用
RegexValidator
添加正则表达式校验
1 | class MyForm(forms.Form): |
choice字段实时更新
1 | from django.forms import Form |
Cookie与Session
目标:
- 为了保持用户登陆状态。
Cookie:
- 登陆之后,将用户的信息返回给用户浏览器,保存在本地,之后访问网站的时候携带保存在浏览器上的用户信息发送给服务端,自动验证。
- 服务端保存在客户端浏览器上的信息都可以称之为cookie。
- 它的表现形式一般都是k:v键值对(可以有多个)。
Session:
- 登陆之后,服务端保存kv键值对形式的数据。k为随机字符串,交由客户端浏览器保存,v为用户信息。
- 数据保存在服务端,并且表现形式一般也是k:v键值对。
- Session是基于Cookie工作的(包括其他保存用户操作的状态都需要使用到cookie)。
Token:
- 为了减轻Session给服务端带来的压力:随着连接数增多,服务端保存的数据量越大。
- 登陆之后,将用户信息进行公司内独有的加密处理,并将多段数据拼接(jwt认证),整体返回给浏览器保存。
- 浏览器之后访问的时候带着密文,服务端自动解密并比对。
Cookie操作
- 虽然cookie是服务端要求客户端需要保存内容,但是客户端可以选择拒绝保存,如果禁止,那么只要是需要记录用户状态的网站功能都无法使用了。
- 如果想要操作cookie,就不得不使用HttpResponse对象。
Cookie方法:
HttpResponseObject.set_cookie(key,value)
:设置cookierequest.COOKIES.get(key)
:获取cookieHttpResponseObject.set_cookie(key, value, max_age, expires)
:在设置cookie的时候可以添加一个超时时间- max_age、expires 都是设置超时时间的,并且都是以秒为单位,针对IE浏览器需要使用expires。
HttpResponseObject.delete_cookie(key)
:清除Cookie
1 | # 校验用户是否登陆的装饰器 |
对装饰器的详细解释:https://www.runoob.com/w3cnote/python-func-decorators.html
Session操作
Session数据是保存在服务端的,给客户端返回的是一个key为sessionid、value为随机字符串的键值对。
在使用Session之前要使用数据库迁移命令,因为Session的数据是存储在django_session表中的。
Django默认session的过期时间是14天。
django_session表中的数据条数是取决于 user-agent ,同一个浏览器在期限内只会有一条数据被写入在表中。
当session过期时,可能会出现多条数据对应一个IP地址,但是该现象不会持续很久,内部会自动清除过期的数据,也可以通过代码手动清除。
session保存位置可以有多种选择:1. MySQL 2. 文件 3. redis 4. memcache
Session方法:
request.session['key'] = value
:设置sessionrequest.session.get('key')
:获取sessionrequest.session.set_expiry()
:设置过期时间- 非零正数:持续的秒数
- datetime或timedelta日期对象:指定日期失效
- 0:一旦浏览器窗口关闭则失效
- None:session会依赖全局session失效策略
request.session.delete()
:清除session,只删服务端的,客户端的不删request.session.flush()
:清除session,浏览器和服务端都清空(推荐使用)request.session.session_key
:会话session的key
1 | def set_session(request): |
利用session实现登陆验证
1 | from functools import wraps |
CBV添加装饰器
加在CBV的get或post方法上
1 | from django.utils.decorators import method_decorator |
加在dispatch方法上
因为CBV中首先执行的就是dispatch方法,所以直接作用于当前类里面的所有的方法
1 | from django.utils.decorators import method_decorator |
加在视图类上
如果get方法和post方法都需要登录校验的话就写两个装饰器。
但method_decorator必须传 name 关键字参数
1 | from django.utils.decorators import method_decorator |