当前位置:  开发笔记 > 编程语言 > 正文

Django中的非全局中间件

如何解决《Django中的非全局中间件》经验,为你挑选了3个好方法。

在Django中有一个设置文件,用于定义要在每个请求上运行的中间件.此中间件设置是全局的.有没有办法在每个视图的基础上指定一组中间件?我希望特定的URL使用一组与全局集不同的中间件.



1> Ned Batcheld..:

你想要的decorator_from_middleware.

from django.utils.decorators import decorator_from_middleware

@decorator_from_middleware(MyMiddleware)
def view_function(request):
    #blah blah

它不适用于URL,但它适用于每个视图,因此您可以对其效果进行细粒度控制.


好的,但如果我想排除中间件而不是附加它们会怎样.例如,我的设置文件列出了中间件MIDDLEWARE_CLASSES =('A','B','C'),我希望一个视图有A和B而不是C.是否有装饰器来删除中间件?只有一个Django应用程序需要这个自定义中间件的东西,因此我不想将"decorator_from_middleware"添加到我的应用程序中的每个其他视图.
`@ csrf_exempt`,它与你所要求的类似,通过在视图上设置一个标志来工作,然后由相应的CSRF中间件检查.当然,这不是一般解决方案,只是注意到.

2> Chase Seiber..:

我对这个问题有一个真正的解决方案.警告; 这有点像黑客.

""" Allows short-curcuiting of ALL remaining middleware by attaching the
@shortcircuitmiddleware decorator as the TOP LEVEL decorator of a view.

Example settings.py:

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

    # THIS MIDDLEWARE
    'myapp.middleware.shortcircuit.ShortCircuitMiddleware',

    # SOME OTHER MIDDLE WARE YOU WANT TO SKIP SOMETIMES
    'myapp.middleware.package.MostOfTheTimeMiddleware',

    # MORE MIDDLEWARE YOU WANT TO SKIP SOMETIMES HERE
)

Example view to exclude from MostOfTheTimeMiddleware (and any subsequent):

@shortcircuitmiddleware
def myview(request):
    ...

"""

def shortcircuitmiddleware(f):
    """ view decorator, the sole purpose to is 'rename' the function
    '_shortcircuitmiddleware' """
    def _shortcircuitmiddleware(*args, **kwargs):
        return f(*args, **kwargs)
    return _shortcircuitmiddleware

class ShortCircuitMiddleware(object):
    """ Middleware; looks for a view function named '_shortcircuitmiddleware'
    and short-circuits. Relies on the fact that if you return an HttpResponse
    from a view, it will short-circuit other middleware, see:
    https://docs.djangoproject.com/en/dev/topics/http/middleware/#process-request
     """
    def process_view(self, request, view_func, view_args, view_kwargs):
        if view_func.func_name == "_shortcircuitmiddleware":
            return view_func(request, *view_args, **view_kwargs)
        return None

编辑:删除了两次运行视图的先前版本.



3> Joe Holloway..:

这是我最近用来解决你在对Ned的回答的评论中提出的场景的解决方案......

它假定:

A)这是一个自定义中间件,或者您可以使用自己的中间件类扩展/包装的中间件

B)你的逻辑可以等到,process_view而不是process_request,因为process_view你可以view_func在解决后检查参数.(或者您可以调整以下代码以使用urlresolversIgnacio指示).

# settings.py
EXCLUDE_FROM_MY_MIDDLEWARE = set('myapp.views.view_to_exclude', 
    'myapp.views.another_view_to_exclude')

# some_middleware.py

from django.conf import settings

def process_view(self, request, view_func, view_args, view_kwargs):
    # Get the view name as a string
    view_name = '.'.join((view_func.__module__, view_func.__name__))

    # If the view name is in our exclusion list, exit early
    exclusion_set = getattr(settings, 'EXCLUDE_FROM_MY_MIDDLEWARE', set())
    if view_name in exclusion_set:
        return None

    # ... middleware as normal ...
    #
    # Here you can also set a flag of some sort on the `request` object
    # if you need to conditionally handle `process_response` as well.

可能有一种方法可以进一步推广这种模式,但这很好地完成了我的目标.

为了回答您更普遍的问题,我认为Django库中没有任何东西可以帮助您解决这个问题.如果django-users邮件列表尚未在那里解决,那将是一个很好的话题.

推荐阅读
云聪京初瑞子_617
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有