问题是我找不到如何设置中间件的示例。我看到了一些覆盖我想要的方法
process_view
的类。Class CheckConditionMiddleware(object):
def process_view(self, request):
return None
但是我应该把这个类放在哪里呢?我要创建一个中间件应用程序,然后把这个类放在其中,并在settings.middleware
中引用它吗?
process_view
的类。Class CheckConditionMiddleware(object):
def process_view(self, request):
return None
但是我应该把这个类放在哪里呢?我要创建一个中间件应用程序,然后把这个类放在其中,并在settings.middleware
中引用它吗?
如果你没有它,你需要在你的应用程序中创建middleware文件夹,并按照以下结构进行:
yourproject/yourapp/middleware
文件夹中间件应该放置在与settings.py、urls和templates相同的文件夹中...
重要提示:不要忘记在middleware文件夹中创建init.py空文件,以便您的应用程序识别此文件夹
现在我们应该为自定义中间件创建一个文件,在本例中假设我们想要一个基于IP过滤用户的中间件,我们在middleware文件夹中创建名为filter_ip_middleware.py的文件,并添加以下代码:
class FilterIPMiddleware(object):
# Check if client IP is allowed
def process_request(self, request):
allowed_ips = ['192.168.1.1', '123.123.123.123', etc...] # Authorized ip's
ip = request.META.get('REMOTE_ADDR') # Get client IP
if ip not in allowed_ips:
raise Http403 # If user is not allowed raise Error
# If IP is allowed we don't do anything
return None
我们需要查找以下内容:
MIDDLEWARE_CLASSES
(django < 1.10)MIDDLEWARE
(django >= 1.10)在 settings.py 中,我们需要添加我们的中间件(将其添加到最后一个位置)。代码应该如下所示:
MIDDLEWARE = ( # Before Django 1.10 the setting name was 'MIDDLEWARE_CLASSES'
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Above are django standard middlewares
# Now we add here our custom middleware
'yourapp.middleware.filter_ip_middleware.FilterIPMiddleware'
)
完成! 现在每个客户端的请求都将调用您的自定义中间件并处理您的自定义代码!
yourproject/yourapp/middleware
。我认为这很明显,但如果这能让你更清楚,我会进行更新。 - AlvaroAV自Django 1.10版本以来,中间件类必须在其__init__()
方法中接受一个get_response
参数并提供一个__call__()
方法。虽然可以通过在定义中间件类时使用django.utils.deprecation.MiddlewareMixin
来实现这一点(如W.Perrin的答案所示),但是在当前支持的Django版本中创建基于类的中间件看起来像这样:
class CustomMiddleware(object):
def __init__(self, get_response):
"""
One-time configuration and initialisation.
"""
self.get_response = get_response
def __call__(self, request):
"""
Code to be executed for each request before the view (and later
middleware) are called.
"""
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
"""
Called just before Django calls the view.
"""
return None
def process_exception(self, request, exception):
"""
Called when a view raises an exception.
"""
return None
def process_template_response(self, request, response):
"""
Called just after the view has finished executing.
"""
return response
process_view()
、process_exception()
和process_template_response()
是特殊的钩子函数,在处理中间件时Django会调用它们,你可以在自己的中间件类中定义。在上面的示例中,实现的钩子函数除了确保Django调用下一个中间件进一步处理响应/请求外,不会有其他特殊操作。
要激活中间件组件,请将其添加到Django设置中的MIDDLEWARE
列表中。
MIDDLEWARE = [
# Default 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',
# Add your custom middleware
'path.to.your.middleware.CustomMiddleware',
]
appname.middleware.middlewarefilename.CustomMiddleware
。 - sid_mac只需要两个步骤。对于 django2.1
我使用以下方法解决了此问题。
1.创建自己的中间件类。
官方手册有很好的演示。
https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.HttpRequest.get_host
from django.utils.deprecation import MiddlewareMixin
class MultipleProxyMiddleware(MiddlewareMixin):
FORWARDED_FOR_FIELDS = [
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED_HOST',
'HTTP_X_FORWARDED_SERVER',
]
def process_request(self, request):
"""
Rewrites the proxy headers so that only the most
recent proxy is used.
"""
for field in self.FORWARDED_FOR_FIELDS:
if field in request.META:
if ',' in request.META[field]:
parts = request.META[field].split(',')
request.META[field] = parts[-1].strip()
2. 在项目的 setting.py
文件的 MIDDLEWARE
列表中引用您的 Middleware 类。
Middleware 引用的规则是从项目的根目录到您的类的路径。
例如,在名为 mysite
的项目中,树形结构如下。
├── mysite
│ ├── manage.py
│ ├── mysite
│ │ ├── __init__.py
│ │ ├── middleware.py
│ │ ├── settings.py
│ │ ├── urls.py
│ │ └── wsgi.py
middleware.py
文件中添加了我们的中间件类MultipleProxyMiddleware
。我们得到以下参考名称。MIDDLEWARE = [
'mysite.middleware.MultipleProxyMiddleware',
...
]
core/
中创建一个名为middleware
的文件夹,并包含__init__.py
(空文件)和custom.py
。*我参考了文档,并使用了Django 4.2.3版本:django-project
|-core
| |-settings.py
| └-middleware # Here
| |-__init__.py
| └-custom.py
|-my_app1
└-my_app2
custom.py
中:# "core/middleware/custom.py"
def simple_middleware(get_response):
print("Here is run only once when the server starts")
def middleware(request):
print("Here is run before a view is run")
response = get_response(request)
print("Here is run after a view is run")
return response
return middleware
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
print("Here is run only once when the server starts")
def __call__(self, request):
print("Here is run before a view is run")
response = self.get_response(request)
print("Here is run after a view is run")
return response
最后,将simple_middleware
和SimpleMiddleware
设置为MIDDLEWARE,然后每次加载Django网站时,都会运行您设置的中间件MIDDLEWARE
:
# "core/settings.py"
...
MIDDLEWARE = [
...
'core.middleware.custom.simple_middleware', # Here
'core.middleware.custom.SimpleMiddleware' # Here
]
...
您是否想在响应中添加一个元素?就像messagemiddleware所做的那样,这个新元素可以被视为django视图发送的上下文
或者您想添加会话,并在每次客户端发出请求时检查会话
,以此为思路,遵循一些固定格式,就像在这个网站中所示https://medium.com/scalereal/everything-you-need-to-know-about-middleware-in-django-2a3bd3853cd6
。当您知道视图中发生了哪种类型的异常时,这将非常有帮助。
基于上述情况,我创建了自己的自定义类,如下所示:
from .models import userDetails
class customMiddleware(object):
def process_request(self,request):
result=''
users = userDetails.objects.all()
print '-->',users ,'---From middleware calling ---'
username=request.POST.get("username")
salary = request.POST.get("salary")
if salary:
try:
result = username+int(salary)
except:
print "Can't add"
当字符串和整数相加时发生异常时,它将被执行。
您可以为上述中间件类编写相应的视图。