Django_Day_6

缓存

  • 提升服务器响应速度

  • 将执行过的操作数据 存储下来,在一定时间内,再次获取数据的时候,直接从缓存中获取

  • 比较理想的方案,缓存使用内存级缓存

  • Django内置缓存框架

  • 创建缓存表:

    •  python manage.py createcachetable my_cache_table:  

    •  缓存表的结构:      
    •  如果需要用redis来存放缓存数据需要额外安装两个包:

pip install django-redis
pip install django-redis-cache
    •   利用数据库来最缓存——在setting表中注册一下cache
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table',
        'TIMEOUT': 60 * 5 # 用于缓存的默认超时(以秒为单位)。 此参数默认为300秒(5分钟)。 您可以将TIMEOUT设置为None,以便默认情况下缓存键永不过期。 值为0 = “不缓存”
          # 详细参数的官方文档:https://docs.djangoproject.com/en/dev/topics/cache/
}, 'redis_backend': { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", # 缓存的位置 "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", #客户端的位置 } } }

 

# @cache_page(30)
def news(request):
    '''
    底层的缓存API方式进行缓存
    有时候不想缓存一个页面,甚至不想某个页面的一部分,只是想缓存某个数据库检索的结果,
    django提供了底层次的API,可以是用这些API来缓存任何粒度的数据,模型对象的字符串,字典,列表等等
    :param request:
    :return:
    '''
    cache = caches['default']
    result = cache.get("news")
    '''如果缓存数据库中有这条信息就直接返回结果'''
    if result:
        return HttpResponse(result)
    '''如果数据库中没有就将这条数据加入到数据库中'''
    news_list = []
    for i in range(10):
        news_list.append("最近贸易战又开始了%d" % i)
    sleep(5)
    data = {
        'news_list': news_list
    }
    response = render(request, 'news.html', context=data)
    cache.set("news", response.content, timeout=60)
    return response


# 秒数,这里指缓存 1 分钟,cache=指定是哪一种缓存
@cache_page(60, cache='default')
def jokes(request):
    '''
    通过装饰器的方式进行单个views的缓存设置——貌似会覆盖掉setting中的设置
    :param request:
    :return:
    '''
    sleep(5)
    return HttpResponse('JokeList')
示例代码

 

 

AOP中间件

  • 实现统计功能

    • 统计IP

    • 统计浏览器

  • 实现权重控制

    • 黑名单

    • 白名单

——通过request模块获取:
     '''案例1:'''
        print(request.META.get("REMOTE_ADDR"))
        ip = request.META.get("REMOTE_ADDR")
        if request.path == "/app/getphone/":
            if ip == "127.0.0.1":
                if random.randrange(100) > 20:
                    return HttpResponse("恭喜您免费获取小米8 256G版")
        '''案例2:'''
        if request.path == "/app/getticket/":
            if ip.startswith("127.0.0.1"):
                return HttpResponse("已抢光")
  • 实现反爬

    • 反爬虫:十秒之内只能搜索一次

    • 实现频率控制

        '''案例4:设置黑名单和小黑屋'''
        black_list = cache.get('black',[]) #设置一个黑名单
        if ip in black_list:
            return HttpResponse("黑名单用户,凉凉")
        requests = cache.get(ip, []) # 获取一下当前访问的ip的,所有访问时间记录
        while requests :
            '''如果这一次访问与上一次访问时间间隔了60s就不对他进行限制'''
            temp = requests[-1]
            if time.time() - float(temp) > 60:
                requests.pop()
            else:
                break
        requests.insert(0, time.time()) #记录一下当前访问及其时间
        cache.set(ip, requests, timeout=60)
        if len(requests) > 30: # 一分钟内访问数量大于30次,设置到黑名单中
            black_list.append(ip)
            cache.set('black', black_list, timeout=60*60*24)
            return HttpResponse("小爬虫小黑屋里呆着吧")
        if len(requests) > 10:# 一分钟内访问数量大一10次
            return HttpResponse("请求次数过于频繁,小爬虫回家睡觉吧")
  • 界面友好化

    • 验证码绘制
def get_code(request):

    mode = "RGB"
    size = (200, 100)
    # 设定颜色随机化
    red = get_color()
    green = get_color()
    blue = get_color()
    color_bg = (red, green, blue)
    # 初始化画布
    image = Image.new(mode=mode, size=size, color=color_bg)
    # 初始化画笔
    imagedraw = ImageDraw(image, mode=mode)
    # 设定显示字体
    '''
    ImageFont.truetype(file,size) ⇒ Font instance
    含义1:加载一个TrueType或者OpenType字体文件,并且创建一个字体对象。
    这个函数从指定的文件加载了一个字体对象,并且为指定大小的字体创建了字体对象。
    '''
    imagefont = ImageFont.truetype(settings.FONT_PATH, 100)
    # 设置绘画内容
    verify_code = generate_code()
    # 把验证码放到session中
    request.session['verify_code'] = verify_code
    # 在画布上画上每一个字
    for i in range(4):
        fill = (get_color(), get_color(), get_color()) # 每一个子的颜色
        imagedraw.text(xy=(50 * i, 0), text=verify_code[i], font=imagefont, fill=fill)
    # 在画布上画上点
    for i in range(5000):
        fill = (get_color(), get_color(), get_color())
        xy = (random.randrange(201), random.randrange(100))
        imagedraw.point(xy=xy, fill=fill)
    # 在画布上画线
    for i in range(20):
        fill = (get_color(), get_color(), get_color())
        x1 = random.randint(0, 201)
        x2 = random.randint(0, 201)
        y1 = random.randint(0, 100)
        y2 = random.randint(0, 100)
        xy = (x1,y2,x2,y1)
        imagedraw.line(xy=xy,fill=fill)
    # 传输到内存流中
    fp = BytesIO()
    image.save(fp, "png")
    return HttpResponse(fp.getvalue(), content_type="image/png")
View Code
  • 应用交互友好化

  • 分页

def get_students_with_page(request):
    page = int(request.GET.get("page", 1))
    per_page = int(request.GET.get("per_page", 20)) # 设定每页显示的人数
    students = Student.objects.all()
    paginator = Paginator(students, per_page)
    page_object = paginator.page(page)
    data = {
        "page_object": page_object,
        'page_range': paginator.page_range
    }
    return render(request, 'students_with_page.html', context=data)
对应的html

中间件

  • 调用顺序

    • 中间件注册的时候是一个列表

    • 如果我们没有在切点处直接进行返回,中间件会依次执行

    • 如果我们直接进行了返回,后续中间件就不再执行了
  • 切点

    • process_request(self,request):在执行视图前被调用,每个请求上都会调用,不主动进行返回或返回HttpResponse对象

    • process_view(self,request,view_func,view_args,view_kwargs):调用视图之前执行,每个请求都会调用,不主动进行返回或返回HttpResponse对象

    • process_template_response(self,request,response):在视图刚好执行完后进行调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象
    • process_response(self,request,response):所有响应返回浏览器之前调用,每个请求都会调用,不主动进行返回或返回HttpResponse对象

    • process_exception(self,request,exception):当视图抛出异常时调用,不主动进行返回或返回HttpResponse对象

    def process_exception(self, request, exception):
        '''
        当视图抛出异常时调用,不主动进行返回或返回HttpResponse对象
        对应 def calc() 和 http://127.0.0.1:8000/app/news/
        :param request:
        :param exception:
        :return:
        '''
        print(request, exception)
        return redirect(reverse('app:index'))
  • 切面

  • 自定义中间件

    • 1. 在工程目录下创建middleware目录

    • 2. 目录中创建一个python文件

    • 3. 在python文件中导入中间件的基类:from django.utils.deprecation import MiddlewareMixin

    • 4. 在类中根据功能需求,创建切入需求类,重写切入点方法 

      • class LearnAOP(MiddlewareMixin):
            def process_request(self,request):
                print('request的路径',request.GET.path)    
    • 5. 启用中间件,在settings中进行配置,MIDDLEWARE中添加:middleware.文件名.类名

  •  csrf豁免权:

     

     

        

homework

  • 分页

    • 页码超过10个的时候,中间的页面使用...代替

    • 显示的时候只显示前五页和后五页

posted @ 2020-02-05 10:28  东坡肉肉君  阅读(99)  评论(0)    收藏  举报