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")
-
应用交互友好化
-
分页
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)

中间件
-
调用顺序
-
中间件注册的时候是一个列表
-
如果我们没有在切点处直接进行返回,中间件会依次执行
- 如果我们直接进行了返回,后续中间件就不再执行了
-
-
切点
-
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个的时候,中间的页面使用...代替
-
显示的时候只显示前五页和后五页
-