form组件源码
forms组件源码
"""
切入点:
form_obj.is_valid()
"""
def is_valid(self):
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()
cookie与session
'''
#由于http协议是无状态的,就有了cookie和session
发展史
1、网站都有保存用户功能的需求 所有用户访问返回的结果都一样的
eg:新闻、博客、文章。。
2、出现了一些需要保护用户信息的网站
eg:淘宝、支付宝、京东。。。
以登录功能为例:如果不保存用户登录状态 也就意味着每次访问网站都需要重新的输入
用户名和密码(这样网站还能用吗?)
当用户第一次登录成功之后 将用户的用户名和密码返回给用户浏览器 让用户浏览器保存在本地,
之后访问网站的时候浏览器自动将保存在浏览器上的用户名和密码发送给服务端 服务端获取后自动验证。
cookie
服务端保存在客户端浏览器上的信息都可以称之为cookie
它的表现形式一般都是K:V键值对(可以有多个)
session
数据保存在服务端的并且它的表现形式一般也是KV键值对(可以有多个)
总结:
1、cookie就是保存在客户端浏览器上的信息
2、session就是保存在服务端上的信息(默认存在数据库里)django_session表
3、session是基于cookie工作的(其实大部分呢的保存用户状态的操作都需要使用到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','lz666',max_age=3,expires=3)
max_age
expires
两者都是设置超时时间的,并且都是以秒为单位
但是expires是针对IE浏览器
'''
#用户登录功能
#校验用户是否登录的装饰器
'''
用户如果在没有登录的情况下想访问一个需要登录的页面,那么先跳到登录页面
,当登录后应该跳的想要访问的页面,而不应该写死,直接跳到home
'''
def login_auto(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'):
res = func(request,*args,**kwargs)
return res
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 == 'lz' and password == '123':
target_url = request.GET.get('next')
if target_url:
obj = redirect(target_url)
else:
#保存用户登录状态
obj = redirect('/home/') #写死了,登录完只能跳到home页面
#让浏览器记录cookie数据
obj.set_cookie('username','lz666')
#跳转到一个需要登录之后才能看到的页面
return obj
return render(request,'login.html')
@login_auto
def home(request):
# if request.COOKIES.get('username')=='lz666':
# return HttpResponse('我是home页面,登录之后才能进来')
#没有登录跳转到登录页面
# return redirect('/login/')
return HttpResponse('我是home页面,登录之后才能进来')
@login_auto
def index(request):
# if request.COOKIES.get('username')=='lz666':
# return HttpResponse('我是home页面,登录之后才能进来')
#没有登录跳转到登录页面
# return redirect('/login/')
return HttpResponse('我是index页面,登录之后才能进来')
@login_auto
def func(request):
# if request.COOKIES.get('username')=='lz666':
# return HttpResponse('我是home页面,登录之后才能进来')
#没有登录跳转到登录页面
# return redirect('/login/')
return HttpResponse('我是func页面,登录之后才能进来')
#注销操作
@login_auto
def logout(request):
obj = redirect('/login/')
obj.delete_cookie('username')
return obj
<form action="" method="post">
<p>username: <input type="text" name="username"></p>
<p>password: <input type="text" name="password"></p>
<input type="submit">
</form>
session操作
'''
session数据是保存在服务端的(但是存在django_session表,这张表你运行了数据库迁移命令产生)
给客户返回的是一个随机字符串
(no such table:django_session)
sessionid:随机字符串
1、在默认的情况下操作session的时候需要django默认一张django_session表
这张表默认的过期时间为14天,也可以手动修改
设置session(看成字典)
request.session['key']=value
获取session
request.session.get('key')
设置过期时间
request.session.set_expiry()
括号内可以放四种类型的参数
1、整数 多少秒
2、日期对象 到指定日期就失效
3、0 一旦当期浏览器窗口关闭立刻失效
4、不写 失效时间就取决于django内部全局session默认的失效时间(14天)
清除session
request.session.delete() #只删服务端的,客户端不删
request.session.flush() #浏览器和服务端的都清空(推荐使用)
session 是保存在服务端的 但是session的保存位置可以有多种选择
1、mysql
2、文件
3、redis
4、memcache
。。。。
django_session表中的数据条数是取决于浏览器的
同一台计算机上(IP地址)同一个浏览器只会有一条数据生效
主要是为了节省服务端数据库资源
'''
def set_session(request):
request.session['hobby']='girl'
return HttpResponse('哈哈')
# 内部发生了几件事:
# 1、django内部会自动生成一个随机字符串
# 2、django内部自动将随机字符串和对应的数据保存到django_session表中
# 3、将产生的随机字符串返回给客户端浏览器保存
def get_session(request):
print(request.session.get('hobby'))
"""
内部发生的事:
1、自动从浏览器请求中获取sessionid对应的随机字符串
2、拿着该字符串去django_session表中查找对应的数据
3、如果比对上了,则将对应的数据取出并以字典的形式封装到request.session中
如果比对不上,则request.session.get()返回的是none
"""
return HttpResponse('嘿嘿')
视图函数(CBV)如何添加装饰器
'''
CBV是基于类的视图,就是使用了类来处理用户的请求,不同的请求我们可以在类中使用不同方法来处理,
这样大大的提高了代码的可读性
path('mylogin/',views.MyLogin.as_view())
FBV(function based views),即基于函数的视图;CBV(class based views);也是基于对
象的视图。说白了就是在每一个views中添加自己专用的方法。
path('func/',views.func),
'''
from django.views import View
from django.utils.decorators import method_decorator
# @method_decorator(login_auto,name='get') #方式2(可以加多个)
# @method_decorator(login_auto,name='post')
class MyLogin(View):
@method_decorator(login_auto) #方式3,会直接作用于当前类里面的所有方法
def dispatch(self, request, *args, **kwargs): #CBV源码,display方法可以看做一个分发方法
super().dispatch(request,*args,**kwargs)
pass
# @method_decorator(login_auto) #方式1
def get(self):
return HttpResponse('get请求')
def post(self):
return HttpResponse('post请求')