django15
昨日回顾
1 form组件:写一个类继承Form,写字段,做数据校验(一直有用),模板渲染(混合开发,前后端分离用不到),校验数据:form=Myform(data=字典),字段参数:error_messages,widget,required,max_length,min_length,label
6 错误信息:err=form.errors.get('__all__')
7 局部和全局钩子
-def clean_字段名(self):
-校验通过返回该字段的数据部分
-校验失败抛出异常ValidationError
-def clean(self)
-校验通过返回cleand_data
-校验失败抛出异常ValidationError
今日内容
form组件校验源码
1 # 读的入口是:form往后开始校验字段
form.is_valid()--->self.errors(BaseForm类)---》self.full_clean()(BaseForm类)--》
-self._clean_fields(局部数据校验)和self._clean_form(全局数据校验)
2 self._clean_fields(BaseForm类)
for name, field in self.fields.items(): # 循环拿出的是一个字段的名字和该字段=后面的内容
try:
# 字段自己的校验(最大值,最小值,是不是邮箱格式等等)
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name): # 反射判断有没有clean_字段名
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError as e:
self.add_error(name, e)
3 self._clean_form(BaseForm类) 全局钩子
try:
cleaned_data = self.clean() # self.clean执行的是自己类的clean方法
except ValidationError as e:
self.add_error(None, e)
面向切面编程(AOP OOP:面向对象编程)
1 django中cookie的使用
# 0 会话跟踪,会话保持
# 1 cookie规范
-记住:当前网站在浏览器上cookie个数和大小有限制
-Cookie大小上限为4KB;
-一个服务器最多在客户端浏览器上保存20个Cookie;
-一个浏览器最多保存300个Cookie;
# 2 django中操作cookie
-增:obj.set_cookie('key','value')
-删: obj.delete_cookie('key') # 设置过期
-查: request.COOKIES.get('key')
-改: obj.set_cookie('key','value1')
# 3 带签名的cookie(加盐,加密)
-增:obj.set_signed_cookie('name','lqz','123') # 第三个参数是盐
-删: obj.delete_cookie('name') # 设置过期
-查: request.get_signed_cookie('name',salt='123')
-改: obj.set_signed_cookie('name','lqz','123')
2 cookie版登陆校验
路由
# cookie版登录
path('login/', views.login),
path('order/', views.order),
path('logout/', views.logout),
path('userinfo/', views.userinfo),
视图函数
## 登录认证装饰器
def login_auth(func):
def inner(request, *args, **kwargs):
# 登录校验
name = request.COOKIES.get('name')
if name:
res = func(request, *args, **kwargs)
return res
else:
path = request.get_full_path()
return redirect('/login/?returnUrl=%s' % path)
return inner
### cookie版登录 不用ajax,因为发送的发送接受如果是ajax,而不是浏览器接收,所以无法删除cookie,只能手动删除,否则删除不了,所以如果一定要用ajax发送那么需要自己手动在ajax加上cookie的值,然后删除时操作js来删除。
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
else:
name = request.POST.get('name')
password = request.POST.get('password')
if name == 'lqz' and password == '123':
# 写入cookie
# 登录成功,重定向之前访问的页面
path = request.GET.get('returnUrl')
if path:
obj = redirect(path)
else:
obj = redirect('/index/')
obj.set_cookie('name', name)
return obj
else:
return HttpResponse('用户名或密码错误')
# def order(request):
# name = request.COOKIES.get('name')
# if name:
# return render(request,'order.html')
# else:
# return redirect('/login')
## 装饰器版本(只要加了装饰器,一旦进入这个视图函数,就表明登录成了)
@login_auth
def order(request):
return render(request, 'order.html')
@login_auth
def userinfo(request):
return render(request, 'userinfo.html')
def logout(request):
obj = HttpResponse('退出登录成功')
obj.delete_cookie('name')
return obj
模板
login.html
<form action="" method="post">
<p>用户名:<input type="text" name="name"></p>
<p>密码:<input type="password" name="password"></p>
<p><input type="submit" value="提交"></p>
</form>
order
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/logout/">点我退出</a>
</body>
</html>
userinfo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户信息页面</h1>
</body>
</html>
3 django中session的使用
1 存在于服务端的键值对
3 session的使用(必须先迁移数据)
-增:request.session['name']=lqz # 一个浏览器一个随机字符串,服务端生成一个随机字符串,把随机字符串和name=lqz数据加密存到django_session表中,在浏览器端,会把这个随机字符串放到cookie中,cookie的key值时sessionid,value是对应的随机字符串,在同一个浏览器中写入第二次的session是不会再次生成随机字符串,还是用以前的,只不过将新增的数据加密后放入表中,而随机字符串是不变的,sessionid是跟浏览器有关,因此同一个浏览器不允许登录多个账户,不同浏览器可以登录同一个账户。
-查:request.session['name']
-改:request.session['name']=egon
-删:del request.session['name']
-设置过期时间:request.session.set_expiry(10) #主要是为了防爬虫
4 session的其它使用
-request.session.setdefault('k1',123) # 有则不变,无则新增
-request.session.get('name',None) # 没有则是默认值None
-del request.session['k1'] # 删除k1对应的数据
-request.session.keys() # 取出所有的键
-request.session.values() # 取出所有的值
-request.session.items() # 取出所有的键值对
-request.session.session_key # 获取那个随机字符串,django_session表中session_key字段
-request.session.clear_expired() # 清除过期的session
-request.session.exists("session_key") # 判断这个随机字符串(session_key字段),有没有数据
-request.session.delete() # 删除所有的值,django_session表中删除当前登录者的这条记录
-request.session.flush() # 干了上面那个事,然后把cookie设置为过期
4 django中session的配置
def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
domain=None, secure=False, httponly=False) # max_age:传个数字,以秒计表示过期时间,有默认值,(如果设置6天后过期:一般写成60*60*24*6便于辨识)
# expires:也是过期时间是传时间对象date=datetime.timedelta(day=9)
# path:默认 / ,表示当前域下的所有路径才会发送cookie,其他路径无效不会发送cookie ,可以更改成其他路径
# domain:在哪个域下有效;secure:是否Https传输cookie;httponly:表示只支持http还是https传输cookie
#session存放的位置
1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3. 文件Session # 如果放在文件中,一般选择pickle存储是二进制,json是明文,所以一般用pickle
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
其他公用设置项:
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)***记住
---了解
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
5 cbv加装饰器
from django.views import View
from django.utils.decorators import method_decorator
# 使用登录认证装饰器
# 用法一
# @method_decorator(login_auth,name='get') 必须叫name
# @method_decorator(login_auth,name='post') 必须叫name
class UserInfo(View):
# 用法二
@method_decorator(login_auth)
def get(self, request, *args, **kwargs):
return HttpResponse('userinfo get')
# 总结:两种用法
-加在类上:@method_decorator(login_auth,name='get')
-加载方法上:@method_decorator(login_auth)
6 中间件简介
# 中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能
# django内置中间件
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', # 如果注释,则取不到request.session
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 读一读SessionMiddleware和CommonMiddleware()
# 自定义中间件,如何使用
def test(a:int) ->list: # 公司一般以此中写法表示传入参数的类型和返回值的类型,如果不期望有返回值就可以写None
# 如果一个类型.后面没有提示,只需要在在后面加上 # type :类型,然后就有提示