Неглобальное промежуточное ПО в Django
В 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
Редактировать: удалена предыдущая версия, которая запускала просмотр дважды.
Вот решение, которое я недавно использовал для решения сценария, который вы представили в комментарии к ответу Неда...
Предполагается, что:
А) это пользовательское промежуточное программное обеспечение или расширение, которое вы можете расширить / обернуть с помощью своего собственного класса промежуточного программного обеспечения
Б) ваша логика может подождать, пока process_view
вместо process_request
потому что в 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 вы можете проверить - требует ли это представление промежуточного программного перехвата.
Лучшее, что я смог найти, это использовать if request.path_info.startswith('...'), чтобы пропустить промежуточное ПО, просто вернув запрос. Теперь вы можете создать промежуточное программное обеспечение только для пропуска, а затем унаследовать это. Может быть, вы могли бы сделать что-то еще проще и сохранить этот список в вашем settings.py, а затем пропустить все это. Если я ошибаюсь, дайте мне знать.
Использование django.core.urlresolvers.resolve()
против request.path
в обертке для промежуточного программного обеспечения, чтобы попытаться увидеть, находится ли представление в приложении, и пропустить обработку, если это так.
Я думаю, что это простой способ исключить представление из промежуточного программного обеспечения.
from django.core.urlresolvers import resolve
current_url = resolve(request.path_info).url_name
if want to exclude url A,
class your_middleware:
def process_request(request):
if not current_url == 'A':
"here add your code"
#settings.py
EXCLUDE_FROM_MY_MIDDLEWARE =set({'custom_app.views.About'})
#middlware.py
from django.conf import settings
class SimpleMiddleware(object):
def __init__(self,get_response):
self.get_response=get_response
def __call__(self,request):
response = self.get_response(request)
return response
def process_view(self,request, view_func, view_args, view_kwargs):
view_function='.'.join((view_func.__module__,view_func.__name__))
exclusion_set=getattr(settings,'EXCLUDE_FROM_MY_MIDDLEWARE',set() )
if view_function in exclusion_set:
return None
print("continue for others views")
def process_exception(self,request, exception):
return HttpResponse(exception)
Django urlmiddleware позволяет применять промежуточное ПО только к представлениям, которые сопоставлены с конкретными URL-адресами.