Неглобальное промежуточное ПО в Django - PullRequest
35 голосов
/ 27 мая 2010

В Django есть файл настроек, который определяет промежуточное программное обеспечение, запускаемое при каждом запросе. Этот параметр промежуточного программного обеспечения является глобальным. Есть ли способ указать набор промежуточного программного обеспечения для каждого просмотра? Я хочу, чтобы конкретные URL использовали набор промежуточного программного обеспечения, отличный от глобального набора.

Ответы [ 8 ]

40 голосов
/ 27 мая 2010

Вы хотите decorator_from_middleware.

from django.utils.decorators import decorator_from_middleware

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

Это не относится к URL-адресам, но работает для каждого просмотра, так что вы можете иметь детальный контроль над его эффектом.

7 голосов
/ 31 августа 2011

У меня есть реальное решение этой проблемы. Предупреждение; это немного взломать.

""" 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

Редактировать: удалена предыдущая версия, которая дважды запускала просмотр.

5 голосов
/ 27 мая 2010

Вот решение, которое я недавно использовал для решения сценария, который вы представили в комментарии к ответу Неда ...

Предполагается, что:

A) это пользовательское промежуточное программное обеспечение или расширение, которое вы можете расширить / обернуть с помощью своего собственного класса промежуточного программного обеспечения

B) ваша логика может ждать до 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, если он еще не был там рассмотрен.

2 голосов
/ 13 октября 2015

Вы можете использовать метод process_view, который вызывается перед вызовом функции просмотра. В process_view вы можете проверить - требует ли это представление перехват промежуточного программного обеспечения.

1 голос
/ 23 августа 2013

Лучшее, что я смог найти, это использовать if request.path_info.startswith ('...'), чтобы пропустить промежуточное ПО, просто вернув запрос. Теперь вы можете создать промежуточное программное обеспечение только для пропуска и затем унаследовать это. Может быть, вы могли бы сделать что-то еще проще и сохранить этот список в вашем settings.py, а затем пропустить все это. Если я ошибаюсь, дайте мне знать.

1 голос
/ 27 мая 2010

Используйте django.core.urlresolvers.resolve() против request.path в оболочке для промежуточного программного обеспечения, чтобы попытаться увидеть, находится ли представление в приложении, и пропустить обработку, если таковая.

0 голосов
/ 23 января 2018

Я думаю, что это простой способ исключить представление из промежуточного программного обеспечения

 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"
0 голосов
/ 11 декабря 2012

Django urlmiddleware позволяет применять промежуточное ПО только к представлениям, сопоставленным с конкретными URL-адресами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...