每日测验

"""
1.什么是cookie和session,你能描述一下它们的由来和工作机制吗(切勿糊弄,敷衍了事)
2.django中如何操作cookie和session,请写出尽量多的操作方法,并针对session的操作方法详细内部发生的事情,django默认的session失效时间是多久(切勿糊弄,敷衍了事)
3.面相对象中的__init__和__new__的区别是什么,利用__new__可以实现什么
4.如何给CBV添加装饰器,列举你所知道的几种方式
"""

内容回顾

  • forms组件源码

    #	入口:form_obj.is_valid()
    
    # 校验字段和钩子函数的执行
    
    # 报错提示 其实可以有两种方式(针对局部钩子函数)
    1.self.add_error()
    2.raise ValidationError() """
    python源码里面使用最频繁的其实就是反射
    """
  • cookie与session

    # 由于http协议是无状态的
    
    # cookie概念
    服务端设置保存在客户端浏览器上的键值对(只要符合前面的定义都可以叫cookie)
    cookie虽然是服务端设置的但是浏览器可以选择不保存 # session概念
    存储在服务端上的键值对(用来标识当前用户) 需要基于cookie才能工作
    其实大部分的保存状态的实现都需要基于cookie来做 # 在web领域没有绝对的安全
    基本上防御措施都需要程序员自己写代码完善,并且之内完善没法杜绝
  • django操作cookie

    # 需要借助于HttpResponse对象
    
    # 设置cookie
    obj.set_cookie(key,value)
    # 超时时间
    obj.set_cookie(key,value,max_age/expires)
    expires 针对IE需要用这个参数 数字是以秒为单位
    # 加盐
    obj.set_signed_cookie(key,value,salt='盐')
    # 获取
    request.COOKIES.get(key)
    request.get_signed_cookie(key,salt='盐')
    # 删除
    obj.delete_cookie(key) """
    校验用户是否登陆才能访问视图函数的装饰器
    能够记录用户在没有登陆之前想要访问的页面,登陆之后跳转到对应的页面
    request.path
    request.path_info
    request.get_full_path()
    """
  • django操作session

    """
    1.session是存储在服务端的 django默认情况下是需要借助于django_session表来存储数据 也就意味着如果你想要操作session那么必须先执行数据库迁移命令让django先把django_session表创建出来(no such table:django_session) 2.django默认的session过期时间是14天 3.session存储在服务端 可以有很多地方存储
    1.表
    2.文件
    3.缓存
    4.其他
    ...
    """
    # 设置
    request.session[key] = value
    """
    三件事
    """
    # 获取
    request.session.get(key)
    """
    三件事
    """
    # 删除
    request.session.delete()
    request.session.flush()
    # 设置超时时间
    request.session.set_expiry()
    1.数字 秒数
    2.datetime/timedelta格式 日期格式
    3.None 参加全局失效策略
    4.0 窗口关闭即失效 """
    基于session实现用户登陆 有时候如果多个视图函数都需要使用到一些数据的话,你也可以考虑将该数据存储到django_session表中,方便后续的使用
    eg:
    登陆验证码(bbs作业会涉及到)
    """
  • CBV如何添加装饰器

    """
    django针对CBV添加装饰器需要你导入一个模块
    """
    from django.utils.decorators import method_decorator # 第一种
    class MyCBV(View):
    def get(self,request):
    return HttpResponse() @method_decorator(login_auth)
    def post(self,request):
    return HttpResponse() # 第二种
    @method_decorator(login_auth,name='post')
    @method_decorator(index_de,name='get')
    class MyCBV(View):
    def get(self,request):
    return HttpResponse() def post(self,request):
    return HttpResponse() # 第三种
    class MyCBV(View):
    @method_decorator(login_auth)
    def dispatch(self,request,*args,**kwargs):
    """
    看CBV源码可以得出 CBV里面所有的方法在执行之前都需要先经过
    dispatch方法(该方法你可以看成是一个分发方法)
    """
    super().dispatch(request,*args,**kwargs) def get(self,request):
    return HttpResponse() def post(self,request):
    return HttpResponse()

今日内容概要

  • django中间件

    首先django自带七个中间件,每个中间件都有各自对应的功能

    并且django还支持程序员自定义中间件

    你在用django开发项目的项目的时候,只要是涉及到全局相关的功能都可以使用中间件方便的完成

    • 全局用户身份校验
    • 全局用户权限校验(补充)
    • 全局访问频率校验
    • ...
  • 基于django中间件一个重要的编程思想(重要)

  • csrf跨站请求伪造

今日内容详细

django中间件

django请求生命周期流程图

"""
django中间件是django的门户
1.请求来的时候需要先经过中间件才能到达真正的django后端
2.响应走的时候最后也需要经过中间件才能发送出去 django自带七个中间件
""" 研究django中间件代码规律
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
] class SessionMiddleware(MiddlewareMixin):
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
def process_response(self, request, response):
return response class CsrfViewMiddleware(MiddlewareMixin):
def process_request(self, request):
csrf_token = self._get_token(request)
if csrf_token is not None:
# Use same token next time.
request.META['CSRF_COOKIE'] = csrf_token
def process_view(self, request, callback, callback_args, callback_kwargs):
return self._accept(request) def process_response(self, request, response):
return response class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
request.user = SimpleLazyObject(lambda: get_user(request))
"""
django支持程序员自定义中间件并且暴露给程序员五个可以自定义的方法
1.必须掌握
process_request process_response
2.了解即可
process_view process_template_response process_exception
"""

如何自定义中间件

"""
1.在项目名或者应用名下创建一个任意名称的文件夹
2.在该文件夹内创建一个任意名称的py文件
3.在该py文件内需要书写类(这个类必须继承MiddlewareMixin)
然后在这个类里面就可以自定义五个方法了
(这五个方法并不是全部都需要书写,用几个写几个)
4.需要将类的路径以字符串的形式注册到配置文件中才能生效
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'你自己写的中间件的路径1',
'你自己写的中间件的路径2',
'你自己写的中间件的路径3',
] """
"""
1.必须掌握
process_request
1.请求来的时候需要经过每一个中间件里面的process_request方法
结果的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
2.如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件
3.如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行
而是直接原路返回(校验失败不允许访问...)
process_request方法就是用来做全局相关的所有限制功能 process_response
1.响应走的时候需要结果每一个中间件里面的process_response方法
该方法有两个额外的参数request,response
2.该方法必须返回一个HttpResponse对象
1.默认返回的就是形参response
2.你也可以自己返回自己的
3.顺序是按照配置文件中注册了的中间件从下往上依次经过
如果你没有定义的话 直接跳过执行下一个 研究如果在第一个process_request方法就已经返回了HttpResponse对象,那么响应走的时候是经过所有的中间件里面的process_response还是有其他情况
是其他情况
就是会直接走同级别的process_reponse返回 flask框架也有一个中间件但是它的规律
只要返回数据了就必须经过所有中间件里面的类似于process_reponse方法 2.了解即可
process_view
路由匹配成功之后执行视图函数之前,会自动执行中间件里面的该方法
顺序是按照配置文件中注册的中间件从上往下的顺序依次执行 process_template_response
返回的HttpResponse对象有render属性的时候才会触发
顺序是按照配置文件中注册了的中间件从下往上依次经过 process_exception
当视图函数中出现异常的情况下触发
顺序是按照配置文件中注册了的中间件从下往上依次经过
""" from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class MyMiddleware1(MiddlewareMixin):
def process_request(self,request):
print('我是第一个自定义中间件里面的process_request方法')
# return HttpResponse('baby!') def process_response(self,request,response):
"""
:param request:
:param response: 就是django后端返回给浏览器的内容
:return:
"""
print('我是第一个自定义中间件里面的process_response方法')
return response def process_view(self,request,view_name,*args,**kwargs):
print(view_name,args,kwargs)
print('我是第一个自定义中间件里面的process_view') def process_template_response(self,request,response):
print('我是第一个自定义中间件里面的process_template_response')
return response def process_exception(self,request,exception):
print('我是第一个中间件里面的process_exception')
print(exception) class MyMiddleware2(MiddlewareMixin):
def process_request(self,request):
print('我是第二个自定义中间件里面的process_request方法') def process_response(self,request,response):
print('我是第二个自定义中间件里面的process_response方法')
return response def process_view(self,request,view_name,*args,**kwargs):
print(view_name,args,kwargs)
print('我是第二个自定义中间件里面的process_view') def process_template_response(self,request,response):
print('我是第二个自定义中间件里面的process_template_response')
return response def process_exception(self,request,exception):
print('我是第二个中间件里面的process_exception')
print(exception) 我是第一个自定义中间件里面的process_request方法
我是第二个自定义中间件里面的process_request方法
<function index at 0x0000021E72065310> ((), {}) {}
我是第一个自定义中间件里面的process_view
<function index at 0x0000021E72065310> ((), {}) {}
我是第二个自定义中间件里面的process_view
我是视图函数index
我是第二个自定义中间件里面的process_response方法
我是第一个自定义中间件里面的process_response方法

csrf跨站请求伪造

"""
钓鱼网站
我搭建一个跟正规网站一模一样的界面(中国银行)
用户不小心进入到了我们的网站,用户给某个人打钱
打钱的操作确确实实是提交给了中国银行的系统,用户的钱也确确实实减少了
但是唯一不同的时候打钱的账户不是用户想要打的账户变成了一个莫名其妙的账户 大学英语四六级
考之前需要学生自己网站登陆缴费 内部本质
我们在钓鱼网站的页面 针对对方账户 只给用户提供一个没有name属性的普通input框
然后我们在内部隐藏一个已经写好name和value的input框 如何规避上述问题
csrf跨站请求伪造校验
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden)如果成功则正常执行
"""

如何符合校验

# form表单如何符合校验
<form action="" method="post">
{% csrf_token %}
<p>username:<input type="text" name="username"></p>
<p>target_user:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form> # ajax如何符合校验
// 第一种 利用标签查找获取页面上的随机字符串
{#data:{"username":'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},#}
// 第二种 利用模版语法提供的快捷书写
{#data:{"username":'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
// 第三种 通用方式直接拷贝官方写好的js验证代码并引用到自己的html页面上即可,注意引入本地文件的时候不要忘记配置静态文件
data:{"username":'jason'} {% load static %}
<script src="{% static 'js/mysetup.js' %}"></script>
<script>
$("#d1").click(function (){
$.ajax({
url:'',
type:'post',
//第一种 利用标签查找获取页面上的随机字符串
//data:{"username":"kk",'csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},
// 第二种 利用模版语法提供的快捷书写
{#data:{"username":'kk','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
// 第三种 通用方式直接拷贝js代码并应用到自己的html页面上即可
data:{"username":'kk'},
success:function (){ }
})
})
</script>

js验证代码(直接拷贝放在本地就可以)

function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
} $.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});

csrf相关装饰器

"""
1.网站整体都不校验csrf,就单单几个视图函数需要校验
2.网站整体都校验csrf,就单单几个视图函数不校验
"""
from django.views.decorators.csrf import csrf_protect,csrf_exempt
from django.utils.decorators import method_decorator
"""
csrf_protect 需要校验
针对csrf_protect符合我们之前所学的装饰器的三种玩法
csrf_exempt 忽视校验
针对csrf_exempt只能给dispatch方法加才有效
"""
# @csrf_exempt
# @csrf_protect
def transfer(request):
if request.method == 'POST':
username = request.POST.get('username')
target_user = request.POST.get('target_user')
money = request.POST.get('money')
print('%s给%s转了%s元'%(username,target_user,money))
return render(request,'transfer.html') #CBV相关装饰器
from django.views import View # @method_decorator(csrf_protect,name='post') # 针对csrf_protect 第二种方式可以
# @method_decorator(csrf_exempt,name='post') # 针对csrf_exempt 第二种方式不可以
@method_decorator(csrf_exempt,name='dispatch')
class MyCsrfToken(View):
# @method_decorator(csrf_protect) # 针对csrf_protect 第三种方式可以
# @method_decorator(csrf_exempt) # 针对csrf_exempt 第三种方式可以
def dispatch(self, request, *args, **kwargs):
return super(MyCsrfToken, self).dispatch(request,*args,**kwargs) def get(self,request):
return HttpResponse('get') # @method_decorator(csrf_protect) # 针对csrf_protect 第一种方式可以
# @method_decorator(csrf_exempt) # 针对csrf_exempt 第一种方式不可以
def post(self,request):
return HttpResponse('post')

补充知识点

# 模块:importlib
"""
需求:从a.py中引用b.py的变量
b.py的位置在 myfile文件下
正常思路 from myfile import b
"""
import importlib
res = 'myfile.b'
#这样也就直接可以通过字符串 拿到不同文件夹里面的变量
# 也是setting文件中中间件文件中直接设置字符串就可以拿到路径的奥秘之处
ret = importlib.import_module(res) # from myfile import b
# 该方法最小只能到py文件名
print(ret)

重要思想

#很有深度 建议直接在项目中看自己是怎么写的
#精髓代码
import settings
import importlib def send_all(content):
for path_str in settings.NOTIFY_LIST: #path_str就是一个个settings里面的字符串 'notify.email.Email',
module_path,class_name = path_str.rsplit('.',maxsplit=1) #rsplit从右往左切只切一次
# module_path = 'notify.email' class_name = 'Email'
# 1 利用字符串导入模块
module = importlib.import_module(module_path) # from notify import email
# 2 利用反射获取类名
cls = getattr(module,class_name) # 拿到真正类的名字:Email、QQ、Wechat
# 3 生成类的对象
obj = cls()
# 4 利用鸭子类型直接调用send方法
obj.send(content)

作业

今日作业
1.整理今日内容至个人博客或笔记中
2.自己编写参考django中间件实现功能可配置插拔式设计体会编程思想

Django学习day12随堂笔记的更多相关文章

  1. Django学习day13随堂笔记

    每日测验 """ 今日考题 1.什么是django中间件,它的作用是什么,如何自定义中间件,里面有哪些用户可以自定义的方法,这些方法有何特点 2.基于django中间件的 ...

  2. Django学习day02随堂笔记

    每日测验 """ 今日考题 1.谈谈你对web框架的认识,简述web框架请求流程 2.python三大主流web框架的区别 3.安装django需要注意的事项有哪些(最少 ...

  3. Django学习day08随堂笔记

    今日考题 """ 今日考题 1.聚合查询,分组查询的关键字各是什么,各有什么特点或者注意事项 2.F与Q查询的功能,他们的导入语句是什么,针对Q有没有其他用法 3.列举常 ...

  4. Django学习day07随堂笔记

    今日考题 """ 今日考题 1.必知必会N条都有哪些,每个都是干啥使的 2.简述神奇的双下划线查询都有哪些方法,作用是什么 3.针对多对多外键字段的增删改查方法有哪些,各 ...

  5. Django学习day05随堂笔记

    每日测验 """ 今日考题 1.反向解析的本质是什么,无名和有名反向解析如何操作? 2..路由分发能够实现的前提是什么,需要注意什么,名称空间什么时候使用 3..什么是虚 ...

  6. Django学习day11随堂笔记

    今日考题 """ 今日考题 1.简述自定义分页器的使用 2.forms组件是干什么用的,它的主要功能有哪些功能,你能否具体说说每个功能下都有哪些经常用到的方法及注意事项( ...

  7. Django学习day10随堂笔记

    每日测验 """ 今日考题 1.默写ajax基本语法,及提交json数据和文件都需要添加哪些额外参数 2.什么是序列化,截止目前为止你所接触过的序列化有哪些 3.批量插入 ...

  8. Django学习day09随堂笔记

    每日测验 """ 今日考题: 1.choices参数的应用场景有哪些,如何获取该字段的值 2.django是什么模型的框架,简述MTV与MVC模型 3.多对多表关系有几种 ...

  9. Django学习day06随堂笔记

    每日测验 """ 今日考题 1.什么是FBV与CBV,能不能试着解释一下CBV的运作原理 2.模版语法的传值需要注意什么,常见过滤器及标签有哪些 3.自定义过滤器,标签, ...

随机推荐

  1. 把对象交给spring管理的3种方法及经典应用

    背景 先说一说什么叫把对象交给spring管理.它区别于把类交给spring管理.在spring里采用注解方式@Service.@Component这些,实际上管理的是类,把这些类交给spring来负 ...

  2. [11 Go语言基础-可变参数函数]

    [11 Go语言基础-可变参数函数] 可变参数函数 什么是可变参数函数 可变参数函数是一种参数个数可变的函数. 语法 如果函数最后一个参数被记作 ...T ,这时函数可以接受任意个 T 类型参数作为最 ...

  3. 见微知著 带你透过内存看 Slice 和 Array的异同

    hi, 大家好,我是 hhf. 有这么一个 Go 面试题:请说出 slice 和 array 的区别? 这简直就是送分题.现在思考一下,你咋样回答才能让面试官满意呢? 我这里就不贴这道题的答案了.但是 ...

  4. SpringBoot返回枚举对象中的指定属性

    枚举 package com.meeno.boot.oa.employee.enums; import com.alibaba.fastjson.annotation.JSONType; import ...

  5. 栈编程和函数控制流: 从 continuation 与 CPS 讲到 call/cc 与协程

    原标题:尾递归优化 快速排序优化 CPS 变换 call/cc setjmp/longjmp coroutine 协程 栈编程和控制流 讲解 本文为部分函数式编程的扩展及最近接触编程语言控制流的学习和 ...

  6. mysql 优化面试题

    第一方面:30种mysql优化sql语句查询的方法 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by涉及的列上建立索引. 2.应尽量避免在 where 子句中使用 ...

  7. ASP.NET Core:ASP.NET Core程序使用Docker部署

    一.前言 这篇文章介绍如何将一个ASP.NET Core应用程序在Docker中进行部署.开发工具使用的是Visual Studio 2019和VS Code. 二.使用Docker部署 我们选择新建 ...

  8. Spring详解(八)------常用的连接池配置

    首先,我们准备Jdbc属性文件 jdbc.properties,用于保存连接数据库的信息,利于我们在配置文件中的使用 jdbc.driver=com.mysql.jdbc.Driver jdbc.ur ...

  9. 二进制I/O

    1 import java.io.BufferedInputStream; 2 import java.io.BufferedOutputStream; 3 import java.io.DataIn ...

  10. 【SpringMVC】获取请求参数

    通过ServletAPI获取 test.html <a th:href="@{/testServletAPI(username='admin',password=123456)}&qu ...