""" 切入点: form_obj.is_valid() """ def is_valid(self): """ Returns True if the form has no errors. Otherwise, False. If errors are being ignored, returns False. """ return self.is_bound and not self.errors # 若是is_valid要返回True的话 那么self.is_bound要为True self.errors要为Flase self.is_bound = data is not None or files is not None # 只要你传值了确定为True @property def errors(self): "Returns an ErrorDict for the data provided for the form" if self._errors is None: self.full_clean() return self._errors # forms组件全部的功能基本都出自于该方法 def full_clean(self): self._clean_fields() # 校验字段 + 局部钩子 self._clean_form() # 全局钩子 self._post_clean()
""" 发展史 1.网站都没有保存用户功能的需求 全部用户访问返回的结果都是同样的 eg:新闻、博客、文章... 2.出现了一些须要保存用户信息的网站 eg:淘宝、支付宝、京东... 以登录功能为例:若是不保存用户登录状态 也就意味着用户每次访问网站都须要重复的输入用户名和密码(你以为这样的网站你还想用吗?) 当用户第一次登录成功以后 将用户的用户名密码返回给用户浏览器 让用户浏览器保存在本地,以后访问网站的时候浏览器自动将保存在浏览器上的用户名和密码发送给服务端,服务端获取以后自动验证 早起这种方式具备很是大的安全隐患 优化: 当用户登录成功以后,服务端产生一个随机字符串(在服务端保存数据,用kv键值对的形式),交由客户端浏览器保存 随机字符串1:用户1相关信息 随机字符串2:用户2相关信息 随机字符串3:用户3相关信息 以后访问服务端的时候,都带着该随机字符串,服务端去数据库中比对是否有对应的随机字符串从而获取到对应的用户信息 可是若是你拿到了截获到了该随机字符串,那么你就能够冒充当前用户 其实仍是有安全隐患的 你要知道在web领域没有绝对的安全也没有绝对的不安全 """ cookie 服务端保存在客户端浏览器上的信息均可以称之为cookie 它的表现形式通常都是k:v键值对(能够有多个) session 数据是保存在服务端的而且它的表现形式通常也是k:v键值对(能够有多个) 下述内容暂时了解便可 先给我搞明白最简单的cookie与session使用再说话! token session虽然数据是保存在服务端的 可是禁不住数据量大 服务端再也不保存数据 登录成功以后 将一段用户信息进行加密处理(加密算法以后你公司开发知道) 将加密以后的结果拼接在信息后面 总体返回给浏览器保存 浏览器下次访问的时候带着该信息 服务端自动切去前面一段信息再次使用本身的加密算法 跟浏览器尾部的密文进行比对 jwt认证 三段信息 (后期会讲 结合django一块儿使用) 总结: 1.cookie就是保存在客户端浏览器上的信息 2.session就是保存在服务端上的信息 3.session是基于cookie工做的(其实大部分的保存用户状态的操做都须要使用到cookie)
# 虽然cookie是服务端告诉客户端浏览器须要保存内容 # 可是客户端浏览器能够选择拒绝保存 若是禁止了 那么 只要是须要记录用户状态的网站登录功能都没法使用了 # 视图函数的返回值 return HttpResponse() return render() return redirect() obj1 = HttpResponse() # 操做cookie return obj1 obj2 = render() # 操做cookie return obj2 obj3 = redirect() # 操做cookie return obj3 # 若是你想要操做cookie,你就不得不利用obj对象 """ 设置cookie obj.set_cookie(key,value) 获取cookie request.COOKIES.get(key) 在设置cookie的时候能够添加一个超时时间 obj.set_cookie('username', 'jason666',max_age=3,expires=3) max_age expires 二者都是设置超时时间的 而且都是以秒为单位 须要注意的是 针对IE浏览器须要使用expires 主动删除cookie(注销功能) """ # 咱们完成一个真正的登录功能 # 校验用户是否登录的装饰器 """ 用户若是在没有登录的状况下想访问一个须要登录的页面 那么先跳转到登录页面 当用户输入正确的用户名和密码以后 应该跳转到用户以前想要访问的页面去 而不是直接写死 """ def login_auth(func): def inner(request,*args,**kwargs): # print(request.path_info) # print(request.get_full_path()) # 可以获取到用户上一次想要访问的url target_url = request.get_full_path() if request.COOKIES.get('username'): return func(request,*args,**kwargs) else: return redirect('/login/?next=%s'%target_url) return inner def login(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if username == 'jason' and password == '123': # 获取用户上一次想要访问的url target_url = request.GET.get('next') # 这个结果多是None if target_url: obj = redirect(target_url) else: # 保存用户登录状态 obj = redirect('/home/') # 让浏览器记录cookie数据 obj.set_cookie('username', 'jason666') """ 浏览器不仅仅会帮你存 并且后面每次访问你的时候还会带着它过来 """ # 跳转到一个须要用户登录以后才能看的页面 return obj return render(request,'login.html') @login_auth def home(request): # 获取cookie信息 判断你有没有 # if request.COOKIES.get('username') == 'jason666': # return HttpResponse("我是home页面,只有登录的用户才能进来哟~") # # 没有登录应该跳转到登录页面 # return redirect('/login/') return HttpResponse("我是home页面,只有登录的用户才能进来哟~")
""" session数据是保存在服务端的(存?),给客户端返回的是一个随机字符串 sessionid:随机字符串 1.在默认状况下操做session的时候须要django默认的一张django_session表 数据库迁移命令 django会本身建立不少表 django_session就是其中的一张 django默认session的过时时间是14天 可是你也能够人为的修改它 设置session request.session['key'] = value 获取session request.session.get('key') 设置过时时间 request.session.set_expiry() 括号内能够放四种类型的参数 1.整数 多少秒 2.日期对象 到指定日期就失效 3.0 一旦当前浏览器窗口关闭马上失效 4.不写 失效时间就取决于django内部全局session默认的失效时间 清除session request.session.delete() # 只删服务端的 客户端的不删 request.session.flush() # 浏览器和服务端都清空(推荐使用) session是保存在服务端的 可是session的保存位置能够有多种选择 1.MySQL 2.文件 3.redis 4.memcache ... django_session表中的数据条数是取决于浏览器的 同一个计算机上(IP地址)同一个浏览器只会有一条数据生效 (当session过时的时候可能会出现多条数据对应一个浏览器,可是该现象不会持续好久,内部会自动识别过时的数据清除 你也能够经过代码清除) 主要是为了节省服务端数据库资源 """ request.session['hobby'] = 'girl' """ 内部发送了那些事 1.django内部会自动帮你生成一个随机字符串 2.django内部自动将随机字符串和对应的数据存储到django_session表中 2.1先在内存中产生操做数据的缓存 2.2在响应结果django中间件的时候才真正的操做数据库 3.将产生的随机字符串返回给客户端浏览器保存 """ request.session.get('hobby') """ 内部发送了那些事 1.自动从浏览器请求中获取sessionid对应的随机字符串 2.拿着该随机字符串去django_session表中查找对应的数据 3. 若是比对上了 则将对应的数据取出并以字典的形式封装到request.session中 若是比对不上 则request.session.get()返回的是None """ # 利用session实现登录验证
from django.views import View from django.utils.decorators import method_decorator """ CBV中django不建议你直接给类的方法加装饰器 不管该装饰器能都正常给你 都不建议直接加 """ # @method_decorator(login_auth,name='get') # 方式2(能够添加多个针对不一样的方法加不一样的装饰器) # @method_decorator(login_auth,name='post') class MyLogin(View): @method_decorator(login_auth) # 方式3:它会直接做用于当前类里面的全部的方法 def dispatch(self, request, *args, **kwargs): return super().dispatch(request,*args,**kwargs) # @method_decorator(login_auth) # 方式1:指名道姓 def get(self,request): return HttpResponse("get请求") def post(self,request): return HttpResponse('post请求')