如何在 Django 中设置自定义中间件

Posted

技术标签:

【中文标题】如何在 Django 中设置自定义中间件【英文标题】:How to set up custom middleware in Django 【发布时间】:2013-08-21 17:59:04 【问题描述】:

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

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

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

        return None  

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

【问题讨论】:

您可以在此处关注我的答案之一:***.com/questions/17751163/… 虽然这是一个很好的答案,但您也可以关注the django book 你可以这样做:***.com/questions/17751163/… @karthikr 您提供的链接已损坏:/ 【参考方案1】:

第一:路径结构

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

yourproject/yourapp/middleware

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

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

二:创建中间件

现在我们应该为我们的自定义中间件创建一个文件,在这个例子中,假设我们想要一个根据用户 IP 过滤用户的中间件,我们在 filter_ip_middleware.py 内创建一个文件 带有此代码的strong>中间件文件夹:

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 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 吗? 是的@tiagovrtr 路径应该是yourproject/yourapp/middleware。我认为这很明显,但如果这让你明白了,我会更新它 检查this answer如果你遇到:TypeError: object() takes no parameters 在this answer 中添加了更新 Django 版本的示例(TypeError: object() takes no parameters的修复)。【参考方案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"

字符串和整数加法发生异常时执行。

你可以为上面的中间件类编写相应的视图

【讨论】:

【参考方案3】:

只需两步。 django2.1 对我有用。

1.创建您自己的中间件类。

官方手册有一个很好的demo。

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 列表中引用您的中间件类。

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

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

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

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

MIDDLEWARE = [
    'mysite.middleware.MultipleProxyMiddleware',  
     ...
]

【讨论】:

【参考方案4】:

在 Django 中编写中间件>=1.10

从 Django 1.10 开始,中间件类必须在其 __init__() 方法中接受 get_response 参数并提供 __call__() 方法。虽然这可以通过在定义中间件类时使用django.utils.deprecation.MiddlewareMixin 来实现(如answer by 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',
]

【讨论】:

【参考方案5】:

首先,中间件实际上是 Httprequest 和 HttpResponse 之间的桥梁,它通常是全局的,因为它是桥梁,因为 HttpRequest 必须通过桥梁到达服务器,并通过 HttpResponse 将桥梁返回客户端。 这很酷,这意味着你可以编写一堆方法在请求到达服务器之前运行,或者在请求到达服务器之后运行。 以csrfmiddleware为例,请求首先由中间件判断其方法是否为POST,如果为真,则中间件将其拥有的csrf_token与服务器内部存储的token进行比较,该token是在发送html时生成的带有form标签,因为一般情况下,客户端只能通过表单服务器直接发送POST请求给客户端,所以服务器可以以此来判断这个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 sendor 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

【讨论】:

以上是关于如何在 Django 中设置自定义中间件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 表单中设置自定义 HTML 属性?

如何在 django 模板中设置自定义 forloop 起点

在 django 中设置自定义用户注册表单的样式

如何在 ActionBar 标题中设置自定义字体?

如何在 iOS 中设置自定义属性? [复制]

如何在 alamofire 5.0.2 版本中设置自定义超时