1、类视图的定义
--类视图定义:
1、继承自 View (from django.views import View)
2、不同的请求方式 有不同的业务逻辑
--如下所示,类试图的方法 就直接采用 http的请求方式的名字 作为我们的函数名.例如: get ,post,put,delete
3、类试图的方法的第二个参数 必须是请求实例对象 ,即 request
--代码示例:
from django.views import View
class BookView(View):
def get(self, request):
return HttpResponse('get request')
def post(self, request):
return HttpResponse('post request')
--类视图 url 定义:
url(r'^login/$', BookView.as_view())
--这种会有问题:
--解决 url结尾不为 / 的报错:
--在settings.py文件中配置APPEND_SLASH = False
--解决 csrf 403 报错
--# 'django.middleware.csrf.CsrfViewMiddleware', 在 MIDDLEWARE 加上这个注释
--视图原理讲解:
--http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] 如果不在这里面,
改源码也没用,因为http协议你改不了
--as_view() 其实就是取出类中的 get put post 这些函数并返回,as_view() --> dispatch()
--as_view() 是通过 @classonlymethod修饰,和 @classmethod修饰的方法一样,属于类方法
-- 关于 40* 错误讲解:
--403 :找到 前端静态资源 但不允许访问
--404 :找不到 前端静态资源
--405 :前端请求像put post get这种到后台没有对应视图接收处理,返回对应静态资源。这种是区别于 50* 的服务器问题的
2、穿插讲解一下:类 python 的一些信息
class Person(object):
# cls 是谁? --> Person 类
@classmethod
def say(cls): # 类方法,不需要实例化直接可以调用
pass
# self 是谁? --> 实例对象
def eat(self): # 实例方法
pass
@staticmethod
def run(): # 静态方法
pass
Person.say()
p=Person()
p.eat()
3、MRO 继承顺序
--mro是一种继承类的调用顺序,具体解释如上图所示
--图上实线表示继承顺序,虚线表示类实例对象调用时查找父类的顺序
4、状态保持 -- cookie [ 设置cookie | 获取cookie ]
--浏览器请求服务器是无状态的。
--无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。
--无状态原因:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。
有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等
--实现状态保持主要有两种方式:
--在客户端存储信息使用Cookie
--在服务器端存储信息使用Session
--当一个无状态请求过来时,我们需要加上cookie,此时示例代码如下所示:
--urls.py中加上
from django.conf.urls import url
from book.views import index, details, BookView, CenterView, CookieView
urlpatterns = [
url(r'^index/$', index, name='goudan'),
url(r'^(?P<book_id>[q|w|e|t]{0,5})/(?P<cat_id>\d{0,4})/', details),
url(r'^login/$', BookView.as_view()),
url(r'^center/$', CenterView.as_view()),
url(r'^cookie_set/$', CookieView.as_view())
]
--在 views.py 中加上 类视图
# 类视图:cookie
class CookieView(View):
def get(self, request):
# 获取请求的参数
username = request.GET.get('name')
# 响应定义
response = HttpResponse('get cookie设置')
response.set_cookie('username_cookies', username, httponly=True, secure=True)
return response
--说明:response.set_cookie('username_cookies', username, httponly=True, secure=True)
--secure属性
当设置为true时,表示创建的 Cookie 会被以安全的形式向服务器传输,也就是只能在 HTTPS 连接中被浏览器传递到服务器端进行会话验证,如果是 HTTP 连接则不会传递该信息,所以不会被窃取到Cookie 的具体内容。
--HttpOnly属性
如果在Cookie中设置了"HttpOnly"属性,那么通过程序(JS脚本、Applet等)将无法读取到Cookie信息,这样能有效的防止XSS攻击。
--刚才 cookie_set 已经设置了cookie,这里只需要定义VerifyCookie类视图即可
--代码如下:
--urls.py 定义:
from django.conf.urls import url
from book.views import \
index, details, BookView, CenterView, CookieView, VerifyCookie
urlpatterns = [
url(r'^index/$', index, name='goudan'),
url(r'^(?P<book_id>[q|w|e|t]{0,5})/(?P<cat_id>\d{0,4})/', details),
url(r'^login/$', BookView.as_view()),
url(r'^center/$', CenterView.as_view()),
url(r'^cookie_set/$', CookieView.as_view()),
url(r'^cookie_send/$', VerifyCookie.as_view())
]
--views.py 文件中定义:
class VerifyCookie(View):
def get(self, request):
# 获取 cookie
cookies = request.COOKIES
# 取出 cookie 中键值
cookie_name = cookies.get('username_cookies')
print(cookie_name)
return HttpResponse('获取到 cookie 了')
5、状态保持 -- cookie 的 http 原理角度讲解
--第一步:request header中没有cookie,发出请求之后,后台设置cookie返回给前端
response headers中就有了cookie,键值对为 set-cookies:cookie值
--第二步:request header中此时有了从第一次返回的set-cookie中取出的 cookie: cookie_value 键值对
--cookie 是基于域名的,且保存在客户端的
6、状态保持 -- cookie 的 过期和删除
--设置过期时间:
def cookie(request):
response = HttpResponse('ok')
response.set_cookie('itcast1', 'python1') # 临时cookie
response.set_cookie('itcast2', 'python2', max_age=3600) # 有效期一小时
return response
--删除 cookie:
response.delete_cookie('itcast2')
response.set_cookie('itcast2', 'python2', max_age=0)
7、session 基础知识
--基础知识
--保存在服务器端的数据叫做:session
--session 的实现依赖于 cookie 【不是非常严格,但值得参考】
--实现基本过程:
--第一次请求:
--前端通过post请求把用户 id 和 密码发过来,cookie中此时为空
--拿到用户账号和密码之后需要和数据库中帐号进行验证,验证通过之后会生成加密的sessionid,sessionid = 加密(session) + 随机值
--生成sessionid之后,服务器会将其加到返回给前端的cookie中,并保存在内存中
--前端接收到 cookie信息之后,会将其保存在 cookie中 [值为 sessionid]
--第二次请求 及其之后的请求:
--发出带有sessionid 的cookie请求
--接受请求进行验证,验证通过之后返回响应
--这里 存入内存 可能就涉及到redis,验证通过可能就涉及到数据库账户密码管理
--有的公司会使用一个账号通用所有系统登陆,此时为了安全一般帐号使用独立的系统管理,因此在某一个部门的系统登陆时一般会涉及到第三方登录验证的情况。所以这里可能就不涉及到数据库中保存有用户帐号及密码的情况,这种需特别关注。
--例如:
QQ号 3ms 支付宝一键登录 微博登录 微信登陆等
--session已经注册在django项目中
--app 注册:
--'django.contrib.sessions',
--middleware 注册:
--'django.contrib.sessions.middleware.SessionMiddleware',
--在数据库迁移之后 migrate makemigrations,会自动生成一个 django-session数据库
--在数据库中有一个 django_session
--desc django_session之后会发现 有三个字段,一般开始时该数据库为空
--session_key
--session_data
--expire_date
8、session 使用
--1、打印 request.COOKIES ,如果一个项目直接启动,不设置cookie 和 session,直接打印request.COOKIES的话,结果如下:
--{'csrftoken': '7bWXrteOkpgYGW5hP2ccmHhd49fBTHD01Zko6XfcuRqp6jpAWdptwt9LtaYv56nY'}
--一个csrftoken,后续研究一下怎么使用吧
--设置session,这是第一次请求设置session
--user_id = 'liming1234'
request.session['user_id'] = user_id
--第二次请求,根据sessionid验证
if param =='once': # 第一次设置session
# 1、打印 cookies
print(request.COOKIES)
print(request.GET.get('username'))
# 2、user_id 为 liming1234
user_id = 'liming1234'
request.session['user_id'] = user_id
return JsonResponse({'sessionid': 'once'})
elif param == 'twice': # 第二次获取session
print(request.COOKIES)
# 以下两种方式都可以取出 session
print(request.session['user_id'])
print(request.session.get('user_id'))
return JsonResponse({'sessionid': 'twice'})
9、session -- 从http考虑
--设置session 的时候做了两件事
--1、将session保存至数据库
--2、将session设置在响应的cookie信息中,设置形式为:
sessionid:xxxxxxxxx
--session 是依赖cookie的,因此如果换了浏览器或者禁用了cookie,session就会失效
--数据库中弃用的session只需要安静等待过期即可,对应字段为 expire_data