中间件

1、中间件是什么?

中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。    就是存在socket和视图函数中间的一种相当于过滤的机构。

中间件共分为:

(1)process_request(self,request)    接受request之后确定所执行的view之前

(2)process_view(self, request, callback, callback_args, callback_kwargs)    确定了所要执行的view之后 view真正执行之前

(3)process_template_response(self,request,response)       view 执行之后,只有在视图函数的返回对象中有render方法才会执行!

(4)process_exception(self, request, exception)       view抛出异常

(5)process_response(self, request, response)

2.能做过什么?
  

1、做IP限制

放在 中间件类的列表中,阻止某些IP访问了;

2、URL访问过滤

如果用户访问的是login视图(放过)

如果访问其他视图(需要检测是不是有session已经有了放行,没有返回login),这样就省得在 多个视图函数上写装饰器了!

3、缓存(还记得CDN吗?)

客户端请求来了,中间件去缓存看看有没有数据,有直接返回给用户,没有再去逻辑层 执行视图函数

3、

注意:
  对于所有请求的批量做处理的时候用中间件
  单独对某几个函数做处理的时候用装饰器

步骤:
1、、先建一个文件夹,里面写一个py文件
2、、然后开始写类
1.中间件就是一个类,类里面写几个方法
class M1(MiddlewareMixin): 必须继承
def process_request(self,request): request:请求里面的所有的东西
print("m1.request_request")
这个方法里面别轻易返回值,要是有返回值就不再继续执行后面的了,执行自己的process_response和上边的response
一般是无返回值的:继续执行后续的中间件和视图函数
def process_response(self,request,response):
return response 2.在settings中的MIDDLEWARE加上路径
文件夹名称.py文件名称.类名
3.找到继承的那个类,吧那个类拿过来
一般不要用导入的方法,不然有时候更新了就没有这个类了,你就把它继承的那个类拿过来,

中间件执行流程:


用户有访问请求,会从中间件最上方的request(接收)一直往下执行,最后到视图函数然后再由中间件从下往上的response(返回)给用户

中间件执行过程中有return值流程:用户有访问请求,会从中间件最上方的request(接收)一直往下执行,直到那个中间件有return值后在当前的中间值返回给用户,(在1.7左右版本)会直接跳到最后的中间件,然后返回给用户。

中间件代码:

Django中的信号及其用法

Django中提供了"信号调度",用于在框架执行操作时解耦.

一些动作发生的时候,系统会根据信号定义的函数执行相应的操作

Django中内置的signal

Model_signals

 
pre_init                        # Django中的model对象执行其构造方法前,自动触发
post_init # Django中的model对象执行其构造方法后,自动触发
pre_save # Django中的model对象保存前,自动触发
post_save # Django中的model对象保存后,自动触发
pre_delete # Django中的model对象删除前,自动触发
post_delete # Django中的model对象删除后,自动触发
m2m_changed # Django中的model对象使用m2m字段操作数据库的第三张表(add,remove,clear,update),自动触发
class_prepared # 程序启动时,检测到已注册的model类,对于每一个类,自动触发
 

Managemeng_signals

pre_migrate                     # 执行migrate命令前,自动触发
post_migrate # 执行migrate命令后,自动触发

Request/response_signals

request_started                 # 请求到来前,自动触发
request_finished # 请求结束后,自动触发
got_request_exception # 请求异常时,自动触发

Test_signals

setting_changed                 # 配置文件改变时,自动触发
template_rendered # 模板执行渲染操作时,自动触发

Datebase_Wrapperd

connection_created              # 创建数据库连接时,自动触发

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,系统会自动触发注册函数

例子,创建数据库记录,触发pre_savepost_save信号

创建一个Django项目,配置好路由映射

models.py中的代码:

from django.db import models

class UserInfo(models.Model):
name=models.CharField(max_length=32)
pwd=models.CharField(max_length=64)

views.py中的代码:

 
from django.shortcuts import render,HttpResponse
from app01 import models def index(request):
models.UserInfo.objects.create(name="mysql",pwd="mysql123")
return HttpResponse("ok")
 

项目的__init__.py文件中代码:

 
from django.db.models.signals import pre_save,post_save

def pre_save_func(sender,**kwargs):

    print("pre_save_func")
print("pre_save_msg:",sender,kwargs) def post_save_func(sender,**kwargs):
print("post_save_func")
print("post_save_msg:",sender,kwargs) pre_save.connect(pre_save_func) # models对象保存前触发callback函数
post_save.connect(post_save_func) # models对象保存后触发函数
 

创建一个index.html网页,用浏览器打开这个项目,在服务端后台打印信息如下:

 
pre_save_func
pre_save_msg: <class 'app01.models.UserInfo'> {'signal': <django.db.models.signals.ModelSignal object at 0x0000000002E62588>,
'instance': <UserInfo: UserInfo object>, 'raw': False, 'using': 'default', 'update_fields': None} post_save_func
post_save_msg: <class 'app01.models.UserInfo'> {'signal': <django.db.models.signals.ModelSignal object at 0x0000000002E62630>,
'instance': <UserInfo: UserInfo object>, 'created': True, 'update_fields': None, 'raw': False, 'using': 'default'}
 

比较打印的结果,可以看到models对象保存后,在打印信息里包含一个"create=True"的键值对.

也可以使用装饰器来触发信号,把上面__init__.py中的代码修改:

 
from django.core.signals import request_finished
from django.dispatch import receiver @receiver(request_finished)
def callback(sender, **kwargs):
print("Request finished!")

则在本次请求结束后自动触发callback函数,在后台"request finished"这句话.

自定义信号

1.定义信号

新建一个项目,配置好路由,在项目根目录下创建一个singal_test.py的文件,内容为

import django.dispatch

action=django.dispatch.Signal(providing_args=["aaaa","bbbb"])

2.注册信号

项目应用下面的__init__.py文件内容:

from singal_test import action

def pre_save_func(sender,**kwargs):

    print("pre_save_func")
print("pre_save_msg:",sender,kwargs) action.connect(pre_save_func)

3.触发信号

views视图函数内容:

from singal_test import action

action.send(sender="python",aaa="",bbb="")

用浏览器打开index.html网页,后台打印信息如下:

pre_save_func
pre_save_msg: python {'signal': <django.dispatch.dispatcher.Signal object at 0x000000000391D710>, 'aaa': '', 'bbb': ''}

由于内置信号的触发者已经集成到Django中,所以会自动调用,而对于自定义信号需要在任意位置触发

Django 之缓存

一、缓存

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

1、配置

a、开发调试

 # 此为开始调试用,实际内部不做任何操作
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
},
'KEY_PREFIX': '', # 缓存key的前缀(默认空)
'VERSION': 1, # 缓存key的版本(默认1)
'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
}
} # 自定义key
def default_key_func(key, key_prefix, version):
"""
Default function to generate keys. Constructs the key used by all other methods. By default it prepends
the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
function with custom key making behavior.
"""
return '%s:%s:%s' % (key_prefix, version, key) def get_key_func(key_func):
"""
Function to decide which key function to use. Defaults to ``default_key_func``.
"""
if key_func is not None:
if callable(key_func):
return key_func
else:
return import_string(key_func)
return default_key_func

b、内存

 # 此缓存将内容保存至内存的变量中
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
} # 注:其他配置同开发调试版本

c、文件

 # 此缓存将内容保存至文件
# 配置: CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 注:其他配置同开发调试版本

d、数据库

 # 此缓存将内容保存至数据库

     # 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', # 数据库表
}
} # 注:执行创建表命令 python manage.py createcachetable

e、Memcache缓存(python-memcached模块)

 # 此缓存使用python-memcached模块连接memcache

     CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
}

f、Memcache缓存(pylibmc模块)

 # 此缓存使用pylibmc模块连接memcache

     CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '/tmp/memcached.sock',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
}

2、应用

@cache_page(15) #超时时间为15秒,这15秒是暂存的状态,当过了15秒又是新状态了

a. 全站使用

 使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存

     MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
# 其他中间件...
'django.middleware.cache.FetchFromCacheMiddleware',
] CACHE_MIDDLEWARE_ALIAS = ""
CACHE_MIDDLEWARE_SECONDS = ""
CACHE_MIDDLEWARE_KEY_PREFIX = ""

b. 单独视图缓存

 方式一:
from django.views.decorators.cache import cache_page @cache_page(60 * 15)
def my_view(request):
... 方式二:
from django.views.decorators.cache import cache_page urlpatterns = [
url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
]

c、局部视图使用

 a. 引入TemplateTag

         {% load cache %}

     b. 使用缓存

         {% cache 5000 缓存key %}
缓存内容
{% endcache %}
 
 
 

Django之文件上传

使用Django框架进行文件上传共分为俩种方式

1
2
3
一、方式一
 
通过form表单进行文件上传
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#=========================================FORM表单上传文件========================================
def f1(request):
#定义f1上传函数
    if request.method=='GET':
#如果是以GET请求
        return render(request,'f1.html')
#返回html模板
    else:
#否则
        import os
#导入模块
        file_obj=request.FILES.get('fafafa')
#通过文件的方式获取文件
        f=open(os.path.join('static',file_obj.name),'wb')
#打开一个文件创建一个文件句柄,写的模式打开
        for chunk in file_obj.chunks():
#循环对象(chunks是块 代表大小的意思)
            f.write(chunk)
#循环获得对象并写到文件中
        f.close()
#通过文件句柄,关闭文件
        return render(request,'f1.html')
#返回到html模板

form表单上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
========================form表单html============================
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/f1/" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <p><input type="text" name="user"></p>
    <p><input type="file" name="fafafa"></p>
    <p><input type="submit" value="提交"></p>
</form>
</body>
</html>
1
2
3
一、方式二
 
通过form组件进行文件上传
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#======================================Form组件上传文件========================================
class F2Form(Form):
#定义一个上传类
    user=fields.CharField()
#字段是字符串类型
    fafafa=fields.FileField()
#字段是文件类型
 
 
def f2(request):
#定义一个f2上传文件的函数
    import os
#导入模块
    if request.method=='GET':
#如果请求方式GET
        obj=F2Form()
#实例化一个对象
        return render(request,'f2.html',{'obj':obj})
#携带obj对象返回html
    else:
#否则
        obj=F2Form(data=request.POST,files=request.FILES)
#实例化对象obj前端标签input获取的数据以request.POST接收,文件信息以request.FILES接收
        if obj.is_valid():
#通过form组件进行校验如果校验成功就执行下边代码
            print(obj.cleaned_data.get('fafafa').name)
#打印文件名称
            print(obj.cleaned_data.get('fafafa').size)
#打印文件大小
            f=open(os.path.join('static',obj.cleaned_data.get('fafafa').name),'wb')
#打开文件并创建文件句柄,以写的模式打开
            for chunk in request.FILES.get('fafafa').chunks():
#循环读取文件对象的内容
                f.write(chunk)
#循环写入到文件中
            f.close()
#通过文件句柄将文件关闭
        return render(request,'f2.html',{'obj':obj})
#携带obj对象返回html模板

form组件上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="POST" action="/f2/" enctype="multipart/form-data">
        {% csrf_token %}
        <p>{{ obj.user }}</p>
        <p>{{ obj.fafafa }}</p>
        <input type="submit" value="提交" />
    </form>
</body>
</html>
 
 
 

Django之中间件&信号&缓存&form上传的更多相关文章

  1. .net core 3.0web_razor page项目_使用中间件接受大文件上传报错_httpRequest.Form threw an exception of type Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException_Request body too large

    前言:在web项目的.net framework时文件上传时,自己常用一般处理程序接受上传文件,上传文件的大小限制是可以项目的webconfig里配置.   到core项目使用一般处理程序变成了中间件 ...

  2. django 12天(跨域,文件上传,下载,cookie,session)

    django 12天(跨域,文件上传,下载) 跨域 什么是跨域 1.协议不同 2.端口不同 3.主机不同 如何解决跨域 1.安装django-cors-headers模块 2.在settings.py ...

  3. Django项目实战之用户头像上传与访问

      1 将文件保存到服务器本地 upload.html <!DOCTYPE html> <html lang="en"> <head> < ...

  4. Django实现注册页面_头像上传

    Django实现注册页面_头像上传 Django实现注册页面_头像上传 1.urls.py 配置路由 from django.conf.urls import url from django.cont ...

  5. Django:学习笔记(8)——文件上传

    Django:学习笔记(8)——文件上传 文件上传前端处理 本模块使用到的前端Ajax库为Axio,其地址为GitHub官网. 关于文件上传 上传文件就是把客户端的文件发送给服务器端. 在常见情况(不 ...

  6. c# 模拟表单提交,post form 上传文件、大数据内容

    表单提交协议规定:要先将 HTTP 要求的 Content-Type 设为 multipart/form-data,而且要设定一个 boundary 参数,这个参数是由应用程序自行产生,它会用来识别每 ...

  7. c# 模拟表单提交,post form 上传文件、数据内容

    转自:https://www.cnblogs.com/DoNetCShap/p/10696277.html 表单提交协议规定:要先将 HTTP 要求的 Content-Type 设为 multipar ...

  8. django 常用方法总结 < 手写分页-上传头像-redis缓存,排行 ...>

    1.不使用自带模块<Paginator>的手写分页功能views.pydef post_list(request): page = request.GET.get('page', 1) # ...

  9. django之中间件、缓存、信号、admin内置后台

    目录: 中间件 缓存 信号 admin后台 一.中间件 1.什么是中间件? 中间件是一个.一个的管道,如果相对任何所有的通过Django的请求进行管理都需要自定义中间件 中间件可以对进来的请求和出去的 ...

随机推荐

  1. (原)matlab导出oracle中blob的jpg数据到图片

    转载请注明出处: https://www.cnblogs.com/darkknightzh/p/10092965.html function write_blob_info(blob) len = b ...

  2. Mongodb系列- java客户端简单使用(CRUD)

    Mongodb提供了很多的客户端: shell,python, java, node.js...等等. 以 java 为例实现简单的增删改查 pom文件: <dependencies> & ...

  3. SQL DCL 数据控制语句

    前言 DCL(Data Control Language)语句:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句.这些语句定义了数据库.表.字段.用户的访问权限和安全级别.主要的语句关键字包 ...

  4. Oracle 18C DBCA建库报ora-01012错误

    操作系统:rhel 7.2 解决方案: 1).设置/etc/systemd/logind.conf中RemoveIPC=no2).重启服务器或者重启systemd-logind重启systemd-lo ...

  5. Redis 分布式锁的实现

    0X00 测试环境 CentOS 6.6 + Redis 3.2.10 + PHP 7.0.7(+ phpredis 4.1.0) [root@localhost ~]# cat /etc/issue ...

  6. OLT、分光器、ONU直接的关系

  7. Kafka文件存储机制及offset存取

    Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日志系统(也可以当做MQ系统),常见可以用于web/nginx ...

  8. 【Manacher算法】最长子回文串

    [Manacher算法] 这个算法用来找出一个字符串中最长的回文子字符串. 如果采取暴力解最长回文子字符串问题,大概可以有两种思路:1. 遍历出所有子字符串找其中最长的回文 2. 从每个字符作为中心, ...

  9. window/linux composer安装/卸载

    packagist库:https://packagist.org/ window  安装 参考地址:https://www.kancloud.cn/thinkphp/composer/35668 1. ...

  10. 手写一个selenium浏览器池

    维护一组浏览器,实现每分钟1000次查询.DriverPool使用变幻版只初始化一次的单例模式.维护每个浏览器的当前是否使用的状态. 不需要等待请求来了,临时开浏览器,开一个浏览器会耽误6秒钟. 可以 ...