Django には、リクエストごとに実行されるミドルウェアを定義する設定ファイルがあります。このミドルウェア設定はグローバルです。ビューごとに一連のミドルウェアを指定する方法はありますか? 特定の URL で、グローバル セットとは異なる一連のミドルウェアを使用したいと考えています。
9 に答える
あなたがしたいdecorator_from_middleware
。
from django.utils.decorators import decorator_from_middleware
@decorator_from_middleware(MyMiddleware)
def view_function(request):
#blah blah
URL には適用されませんが、ビューごとに機能するため、その効果をきめ細かく制御できます。
この問題に対する本当の解決策があります。警告; それはちょっとしたハックです。
""" 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
編集:ビューを2回実行した以前のバージョンを削除しました。
これは、Nedの回答へのコメントで提示したシナリオに対処するために最近使用したソリューションです...
次のことを前提としています。
A) これはカスタム ミドルウェア、または独自のミドルウェア クラスで拡張/ラップできるミドルウェアです。
B) ロジックはprocess_view
の代わりにまで待機できます。これは、パラメーターが解決された後にパラメーターを調べることができるためですprocess_request
。(または、以下のコードを調整して、Ignacio の指示に従って使用することもできます)。process_view
view_func
urlresolvers
# 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 メーリング リストの良いトピックになります。
ビュー関数を呼び出す前に呼び出される process_view メソッドを使用できます。process_view で、このビューがこのミドルウェアのインターセプトを必要とするかどうかを確認できます。
django.core.urlresolvers.resolve()
ミドルウェアのラッパーでに対してを使用しrequest.path
て、ビューがアプリ内にあるかどうかを確認し、含まれている場合は処理をスキップします。
Django urlmiddlewareを使用すると、特定の URL にマップされたビューにのみミドルウェアを適用できます。