复习Day02
day01作业讲解
# 核心代码(中间件)
from django.utils.deprecation import MiddlewareMixin
import json
class JsonMiddel(MiddlewareMixin):
def process_request(self, request):
try:
request.data=json.loads(request.body)
except Exception as e:
request.data=request.POST
需要关注的问题:
(1)form表单和ajax的提交重复,form表单中的input的submit类型和button按钮都会触发两次(如果有ajax的情况下)。`正确的使用方式`:(input的button类型);
(2)from django.http.request import QueryDict,QueryDict的本质是一个字典,比字典强大,不能修改和删除、增加,否则会报错。
CommonMiddleware中间件控制了是否重定向到带/的地址
查看QueryDict源码,发现:
其通过self._assert_mutable()来控制QueryDict的元素是不可变的
self._mutable = mutable # mutable=False
def _assert_mutable(self):
if not self._mutable:
# querydict实例是不可变的
raise AttributeError("This QueryDict instance is immutable")
python中的魔法方法
# __init__()方法,类实例化会调用该方法
# __str__()方法,打印对象会触发该方法的运行
# __call__()方法,对象()会调用类的__call__方法
基于python中一切皆对象,类实例化的过程中会调用元类的__call__方法
# __new__()方法:在类实例化会触发,比__init__早
# __del__:在对象被回收的时候会触发
# __setattr__,__getattr__:(.拦截方法),当对象.属性-->赋值会触发__setattr__;如果是取值会调用__getattr__
# __setitem__,__getitem__:([]拦截方法),
# __enter__,__exit__:with上下文管理器
setattr,getattr,setitem,getitem
class Beast(object):
def __init__(self,name):
self.name = name
@staticmethod
def check_attr(key,value):
check_list=[key,value]
for item in check_list:
if not isinstance(item,str):
raise TypeError('...')
elif not item or item.isspace():
raise Exception('...')
def __setattr__(self,key,value):
self.check_attr(key,value)
surper(Beast,self).__setattr__(key,value)
def __setitem__(self,key,value):
self.check_attr(key,value)
setattr(self,key,value)
def __getitem__(self,item):
return getattr(self,item)
# 字典
class MyDict(dict):
def __setattr__(self,key,value):
self[key] = value
def __getattr__(self,item):
return self[item]
mydic=MyDict(name='lqz',age=18)
# print(mydic['name'])
print(mydic.name)
# mydic.name=99
# print(mydic.name)
注意:
obj.name = 10会触发__setattr__(self,key,value),在__setattr__中不能使用如self.key = value这种操作,会产生递归调用的现象
obj['name'] = 'lxx'会触发__setitem__(self,key,value),在__setitem__中,不能使用如self[key]=value这种操作,否则会产生递归调用的现象
with上下文管理器
import pymysql
DATABASE_INFO = {
'host':'127.0.0.1',
'port':3306,
'user':'root',
'password':'123456',
'database':'day48',
'charset':'utf8'
}
class MySQLCon(object):
def __init__(self,**kwargs):
self.parameter = kwargs
def __enter__(self):
# 创建数据库对象
self.conn = pymysql.connect(**self.parameter)
# 创建游标对象
self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor)
return self
def __exit__(self,exc_type, exc_val, exc_tb):
# 销毁数据库对象和游标对象
self.cursor.close()
self.conn.close()
# 查询数据
def data_query():
with MySQLCon(**DATABASE_INFO) as sqlObj:
sql = "select name,password from book"
sqlObj.cursor.execute(sql)
print(sqlObj.cursor.fetchall())
# 插入数据
def data_insert():
with MySQLCon(**DATABASE_INFO) as sqlObj:
sql = "insert into book(name,password) values (%s,%s)"
sqlObj.cursor.execute(sql,['surpass','123456'])
sqlObj.conn.commit()
# 删除数据
def data_delete():
with MySQLCon(**DATABASE_INFO) as sqlObj:
sql = "delete from book where name=%s"
sqlObj.cursor.execute(sql,['surpass'])
sqlObj.conn.commit()
# 更新数据
def data_update():
with MySQLCon(**DATABASE_INFO) as sqlObj:
sql = "update book set name=%s where id=%s"
sqlObj.cursor.execute(sql,['surpass',1])
sqlObj.conn.commit()
eq
class Foo(object):
def __init__(self,x,y):
self.x = x
self.y = y
def __eq__(self,obj)
if self.x+self.y == obj.x+obj.y:
return True
else:
return False
f1 = Foo(1,2)
f2 = Foo(2,1)
print(f1 == f2) # True
Cookie,session,token
http 协议的四大特性:
(1)基于请求和响应(request and response);
(2)基于tcp/ip并作用于应用层之上的协议;
(3)无连接/短连接
(4)无状态
随着电商网站和博客网站的发展,保存用户的登录状态这一需求显得尤为重要。因此,出现了如Cookie、Session、Token等技术。
Cookie:存储在浏览器(客户端)的键值对,向服务器发送请求,会携带这个键值对去后端校验,不安全(如果键值对中含有用户的敏感信息)
Session:存储在服务端的键值对(存储形式:文件中、数据库中,甚至内存中),Session是一项基于Cookie的技术,将sessionid存储到Cookie中,客户端每次请求时,会携带这个sessionid去后端拿出session信息进行校验。
缺陷:如果用户量大,会浪费服务器资源
token:本质上就是字符串(既安全,又可以存放个人信息,存放在浏览器),加密字符串
token现在应用非常广泛,契合了前后端分离
JWT:json web token
Django中Session的底层原理
通过查看SessionMiddleware
的源码,我们可以了解django的session 的底层原理:
当请求走的时候:
# 在SessionMiddleware的process_response()中,会先取出requset.session的modify属性,如果该属性为True,表示在视图函数中修改过session,则数据库要同步修改;如果是False,会返回给前端一个随机字符串(sessionid)
当请求来的时候
# 通过浏览器Cookeie中存储的sessionid,拿出随机字符串,拿着这个随机字符串去数据库中查找,将查找到的结果转换成字典,然后赋值给request.session
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
异常处理机制
# 异常处理中的else什么时候执行?
try:
print("xxx")
# print(1/0)
except Exception as e:
print(e)
else: # 基本上不会用到
print("正常执行,没有出异常,会走")
finally:
print("我是finally") # 用于会走,无论是否有异常