Django进阶:CSRF源码分析,分页器,中间件,缓存,信号详解

引子

比如我想和我的某个同学去吃饭,但是我和他前面隔着好几排人,我要找到她,那我就得穿过这几排人

CSRF
CSRF是啥子玩意啊

它叫防跨站请求伪造,之前很多同学刚初学Django,可能会直接把CSRF中间件给去掉,或者在表单上加个{% csrf_token %},但是原理是啥?其实我们可以用{ csrf_token }在前端中显示一下,发现其实它就是一个字符串,当我们以get请求来访问服务器的时候,服务器不仅会返回内容,还会给我们一个加密的字符串,这个加密的字符串只有服务器能反解,客户端提交数据的时候,必须带着这个字符串过来,否则我就不给你提交。

CSRF有啥作用

就是防跨站请求伪造喽,用大白话说就是防止黑客往我们的表单上提交数据,加了CSRF后我们的表单上以及ajax方式提交都要做处理。

分页器

Django里面内置了paginator分页器,
from django.core.paginator import Paginator

  • 使用Django的分页器,语法是后端先用object.all()查询出一个queryset对象,
  • 然后以queryset对象和每页创建多少个数据为参数创建一个Paginator对象,
  • 并且要记得使用try来捕捉用户输入错误URL的异常
def index(request):
    # 批量导入
    # book_list = []
    # for i in range(100, 200):
    #     obj = models.Book(price=i*i, name='这是第'+str(i)+'本书')
    #     book_list.append(obj)
    # models.Book.objects.bulk_create(book_list)
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 10)
    print('paginator count:',paginator.count)
    print('num_page', paginator.num_pages)
    print('page_range', paginator.page_range)
    try:
        current_page = int(request.GET.get('page', 1))
        page = paginator.page(current_page)
        # 如果页数十分多时,换另外一种显示方式
        if paginator.num_pages > 10:
            # 显示前五个页码
            if current_page-5 < 1:
                page_range = range(1, 11)
            elif current_page+5 > paginator.num_pages:
                page_range = range(paginator.num_pages-10, paginator.num_pages+1)
            else:
                page_range = range(current_page-5, current_page+5)
        print('object_list:', page.object_list)
        for i in page:
            print(i)
    except EmptyPage as e:
        # 也会URL输错了,就回到第一页
        page = paginator.page(1)
    return render(request, 'index.html', locals())

index.html代码,因为注释很详细,我就不一一说了哈

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <link rel="stylesheet" href="/static/bootstrap-3.3/css/bootstrap.css"/>
   <link rel="stylesheet" href="/static/bootstrap-3.3/css/bootstrap-theme.css"/>
   <style>

   </style>
</head>
<body>
   <!-- 打印出内容 -->
   {% for item in page  %}
       {{ item.price }}-{{ item.name }}<br>
   {% endfor %}
   <nav aria-label="Page navigation">
     <ul class="pagination">
     {% if page.has_previous %}
       <li>
         <a href="?page={{ page.previous_page_number }}" aria-label="Previous">
           <span aria-hidden="true">上一页</span>
         </a>
       </li>
     {% else %}
         <!-- 没有前一页就设置为disabled -->
       <li>
         <a href="#" aria-label="Previous" class="disabled">
           <span aria-hidden="true">上一页</span>
         </a>
       </li>
     {% endif %}
       <!-- 设置选中的块为深色 -->
       {% for item in page_range %}
           {% if item == current_page %}
               <li class="active"><a href="?page={{ item }}">{{ item }}</a></li>
           {% else %}
               <li><a href="?page={{ item }}">{{ item }}</a></li>
           {% endif %}
       {% endfor %}
     {% if page.has_next %}
       <li>
         <a href="?page={{ page.next_page_number }}" aria-label="Next">
           <span aria-hidden="true">下一页</span>
         </a>
       </li>
     {% else %}
         <!-- 如果没有下一页,也让标签disabled -->  
       <li>
         <a href="#" aria-label="Next" class="disabled">
           <span aria-hidden="true">下一页</span>
         </a>
       </li>
     {% endif %}
     </ul>
   </nav>
</body>
</html>
中间件
中间件是啥玩意

他是在浏览器和服务器中间的钩子,我们一个请求过来的时候,在到达view层之前,需要先穿过一系列的中间件,比如CSRF防护等等,然后在view层返回请求给浏览器的时候也要经过中间件,在Django1.10后的版本,当某个请求在一个中间件中被阻断的话(比如CSRF防护),它会从这个中间件返回,而不是继续穿过后面的中间件到达view函数,但是在Django早期的版本,请求过不了某个中间件的时候,它会一直走完最后一个中间件再往回走,反正不管怎样,被某个中间件阻断后都不会到达视图层。

中间件干啥用的

中间件可以在请求到达view函数之前先对请求做一些操作,或者做一些安全策略,比如我们想过滤掉某些IP,不给这些IP访问,我们可以自己自定义一个中间件,同时,Django自带了很多的中间件,比如CSRF防护,请求必须先穿过这个保护屏障才能到达我们的view函数。

自定义中间件
  • 在Django项目下创建一个文件夹,在这个文件夹下diy一个中间件
from django.utils.deprecation import MiddlewareMixin

class One(MiddlewareMixin):

    def process_request(self, request):
        print('我是第一层process_request')

    def process_response(self, request, response):
        print('我是第一层process_response')
        return response


class Two(MiddlewareMixin):

    def process_request(self, request):
        print('我是第二层process_request')

    def process_response(self, request, response):
        print('我是第二层process_response')
        return response


class Three(MiddlewareMixin):

    def process_request(self, request):
        print('我是第三层process_request')

    def process_response(self, request, response):
        print('我是第三层process_response')
        return response
  • 把自定义中间件写到配置文件里边
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',
    'm.diymiddle.One',
    'm.diymiddle.Two',
    'm.diymiddle.Three',
]

view层

def test(request):
    print('i love django')
    return HttpResponse('OK')
面试

你用中间件做过什么?

  • 基于角色的权限控制
  • 用户认证
  • 过滤黑名单
  • csrf(说原理)
  • session(说原理)
缓存
缓存是什么以及干啥的

因为我们的网站大部分是动态的 请求都会去数据进行相应的操作,如果程序访问量很大,耗时就会增加,这时候最简单的方法就是使用缓存,将view的返回值保存到内存里边,5分钟内再有人来访问就直接去Redis里面拿,或者去内存里边拿,然后再返回。

Django支持的缓存

在很多的web框架都没有这东西,就Django有,缓存也特别简单,只要配置上就行。
Django里面的6种缓存方式:

  • 开发调试(默认的),这个是闹着玩的,实际内部不做任何操作
  • 内存,配置内存版本的时候,必须设置一个值,这个值是唯一的,此缓存将内容保存至内存的变量中
  • 文件
  • 数据库
  • Memcache缓存(使用Python的模块),这个就和Django没什么关系了。
缓存的应用
  • 全站缓存(在整个网站都做缓存):应用较少,使用中间件
  • 在单个view函数上使用:导入cache_page,@cache_page(10)10表示超时时间为10秒,在要缓存的函数上用cache_page装饰一下
  • 局部模板使用缓存:这是一种更小,更细粒度的缓存,这个就太有用了,因为我们网站很少每个地方都用缓存的,只有那些不变的数据才做缓存。
{% load cache %}
信号
信号是什么

Django在很多地方都给我们留了一些钩子,Django中提供了信号调度,用于在框架执行操作时的解耦,通俗来讲,就是一些动作发生的时候,信号允许太特定的发送者去提醒一下接受者

信号

信号的作用就大了

  • 比如说我们去监控我们的服务器的时候,可以达到某个阀值就触发一个信号,然后触发微信通知等等
  • 比如我们想在每次插入数据记录的时候都加一条日志

看一个新浪面试题:如果我想在每个数据库操作的时候都给他加一条日志,怎么做?
这时候,可能很多人想到装饰器,…之前…之后嘛,就是用装饰器,但是装饰器它的粒度不够细,所以答案是用Django的内置信号。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值