98

我正在尝试创建中间件以选择性地将 kwarg 传递给满足条件的每个视图。

问题是我找不到如何设置中间件的示例。我已经看到了覆盖我想要的方法的类process_view

Class CheckConditionMiddleware(object):  
    def process_view(self, request):  

        return None  

但是我把这门课放在哪里呢?我是否要创建一个中间件应用程序并将此类放入其中,然后在其中引用它settings.middleware

4

5 回答 5

164

一:路径结构

如果您没有它,您需要按照以下结构在您的应用程序中创建中间件文件夹:

yourproject/yourapp/middleware

文件夹中间件应该和settings.py、urls、templates放在同一个文件夹中...

重要提示:不要忘记在中间件文件夹中创建init .py 空文件,以便您的应用识别此文件夹

二:创建中间件

现在我们应该为我们的自定义中间件创建一个文件,在这个例子中,假设我们想要一个基于 IP 过滤用户的中间件,我们在中间件文件夹中创建一个名为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

第三:在我们的“settings.py”中添加中间件

我们需要寻找:

  • 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'
)

完毕!现在每个客户端的每个请求都会调用您的自定义中间件并处理您的自定义代码!

于 2015-08-27T06:24:16.917 回答
11

在 Django>=1.10 中编写中间件

从 Django 1.10 开始,中间件类必须在其方法中接受get_response参数__init__()并提供__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 将调用下一个中间件来进一步处理响应/请求。

激活中间件

要激活中间件组件,请将其添加到MIDDLEWAREDjango 设置中的列表中。

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',
]

于 2021-02-08T07:39:44.853 回答
7

只需两步。它适用于我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()

MIDDLEWARE2.在项目setting.py文件列表中引用您的中间件类。

中间件引用的规则是从项目的根目录到您的类的路径。

例如,在一个名为 的项目mysite中,树如下所示。

├── mysite
│   ├── manage.py
│   ├── mysite
│   │   ├── __init__.py
│   │   ├── middleware.py
│   │   ├── settings.py
│   │   ├── urls.py
│   │   └── wsgi.py

我们只需MultipleProxyMiddlewaremiddleware.py文件中添加我们的中间件类。我们得到以下参考名称。

MIDDLEWARE = [
    'mysite.middleware.MultipleProxyMiddleware',  
     ...
]
于 2018-08-27T14:31:35.023 回答
0

首先,中间件实际上是 Httprequest 和 HttpResponse 之间的桥梁,它通常是全局的,因为它是桥梁,因为 HttpRequest 必须通过桥梁到达服务器,并通过 HttpResponse 将桥梁返回客户端。这很酷,这意味着你可以编写一堆方法在请求到达服务器之前运行,或者在请求到达服务器之后运行。以csrfmiddleware为例,请求首先由中间件判断其方法是否为POST,如果为真,则中间件将其拥有的csrf_token与服务器内部存储的token进行比较,该token是在发送HTML时生成的带有form标签,因为通常情况下,客户端只能通过表单服务器直接发送POST请求给客户端,so server 可以以此来判断这个 POST 是否来自表单服务器发给你的,并结合认证或授权,决定是向服务器发送请求还是仅仅反对请求。所以,当你编写自己的中间件时,要清楚你想对请求或响应做什么,do you want to add an element in the response? Like the messagemiddleware did, this new element can be seen as the context django view send or you want to add session, and check the session everytime the client make a request,带着这种心态,遵循一些固定的格式,比如这个网站https://medium.com/scalereal/everything-you-need-to-know-about-middleware-in-django-2a3bd3853cd6

于 2022-01-03T10:40:17.303 回答
-2

如果您知道视图中发生了哪种类型的异常,这将很有帮助。从上面我创建了自己的自定义类,例如

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"

在字符串和整数加法的情况下发生异常时执行。

您可以为上述中间件类编写相应的视图

于 2016-03-14T13:34:01.400 回答