2013-12-21 4 views
6

Вопрос:Доступ к текущему экземпляру класса вида в Django промежуточного

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

Например, если класс на основе зрения, как это:

# views.py 
class MyView(View): 
    my_attribute = 'something' 

Я хотел бы быть в состоянии получить ручку на my_attribute в ПО промежуточного слоя, делая что-то вроде этого:

# middleware.py 
def process_view(self, request, view_func, view_args, view_kwargs): 
    my_attribute = request.view.my_attribute 

Конечно, это не работает, потому что Django не выставляет экземпляр представления через объект запроса. Есть ли способ добиться этого?

Спасибо!


Моя первая попытка:

Первоначально я полагал, что метод process_view() может быть хорошим местом, чтобы сделать это. К сожалению, аргумент view_func, который он получает, содержит функцию - результат MyView.as_view() - а не сам экземпляр представления. Из Django docs:

process_view (самости, запрос, view_func, view_args, view_kwargs)

... view_func функция Python, что Django собирается использовать. (Это фактическая функция объекта, а не имя функции в виде строки.) ...


Моя вторая попытка:

Дескриптор экземпляра вида доступен в process_template_response(), но это довольно неудобно, и в любом случае я хотел бы иметь возможность работать с my_attribute в более ранней точке стека промежуточного программного обеспечения. Но это действительно так:

def process_template_response(self, request, response): 
    my_attribute = response.context_data['view'].my_attribute 
+0

чем проблема вы пытаетесь решить? –

+0

@ burhan-khalid: Цель состоит в размещении некоторых данных в контексте шаблона в зависимости от значения атрибута view. Я бы сделал это с помощью процессора контекста, но не нашел способ доступа к экземпляру представления в процессоре контекста. Мой текущий подход заключается в использовании mixin, который переопределяет 'get_context_data()'. Это выполняет свою работу, но эта функция требуется для каждого запроса, поэтому я бы хотел избежать наследования из mixin в каждом отдельном представлении приложения. – tino

+0

Я могу придумать и ряд других приложений. всего лишь один пример: простой способ управления доступом к просмотру. Я знаю, что есть другие способы управления доступом, но это кажется особенно простым методом, и мне бы хотелось узнать, возможно ли это. – tino

ответ

2

Там нет встроенного способа сделать это, но вот решение, данное мне любезным пользователем в списке рассылки django-users. Я пересказываю его предложение здесь, если кто-то пытается сделать то же самое.

Это полезен, если:

  1. вы хотите, чтобы определить свойства текущего вида в вашем промежуточном слое и выполнять обработку соответственно, и;
  2. по различным причинам вы не хотите использовать миксины или декораторы для достижения аналогичных результатов.

Это проверяет view_func объекта, передаваемого в process_view() промежуточного крючок и определяет и импортирует соответствующий класс просмотра.

# middleware.py 
from myutils import get_class 

def process_view(self, request, view_func, view_args, view_kwargs): 
     view = get_class(view_func.__module__, view_func.__name__) 
     view.my_attribute 

Тогда ваше get_class() определение:

# myutils.py 
from django.utils import importlib 

def get_class(module_name, cls_name): 
    try: 
     module = importlib.import_module(module_name) 
    except ImportError: 
     raise ImportError('Invalid class path: {}'.format(module_name)) 
    try: 
     cls = getattr(module, cls_name) 
    except AttributeError: 
     raise ImportError('Invalid class name: {}'.format(cls_name)) 
    else: 
     return cls 
0

Если это зависит от вида, вероятно, это должно быть микширование этого вида. Если вы делаете что-то вроде меню, которое зависит от активного вида, я бы обратный поиск имени текущего URL:

see a previous answer about using URL name lookup of the current URL

+0

Это, безусловно, потенциальные обходные пути в некоторых случаях. Но Mixins должны быть объявлены в иерархии наследования каждого представления, что может стать проблемой, если вам нужен mixin практически везде. Разве это не ситуация, с которой лучше справляется промежуточное ПО? И если путь доступен через 'request.path_info', почему бы не сделать сам экземпляр представления доступным в' request.view'? Еще более удивительно: экземпляр представления доступен в _template context_: я могу захватить атрибут вида просто с помощью '{{view.my_attribute}}' ... но для его обработки мне нужно использовать тег шаблона. Странный. – tino

+0

Извините за касательную, но не будет ли это отличным расширением для представлений на основе классов, чтобы иметь возможность напрямую работать с экземпляром представления? Это позволит вам делать некоторые вещи по всем направлениям, которые в настоящее время вы можете выполнять только с микшинами на индивидуальной основе. Или с декораторами, которые являются довольно недоступными для новичков. В любом случае кажется глупым разоблачить экземпляр представления в шаблонах, но не через объект запроса. И, кроме того, я мог бы просто просто пропустить что-то совершенно фундаментальное. :) – tino

1

Другим решением может быть, чтобы создать новый вид класса:

from django.views.generic.base import View 
class AddClassView(View): 
    @classonlymethod 
    def as_view(cls, **initkwargs): 
     view = super(AddClassView, cls).as_view(**initkwargs) 
     view.cls = cls 
     return view 

И использовать это в своем классе на основе зрения:

# views.py 
class MyView(AddClassView): 
    my_attribute = 'something' 

Затем выполните следующие действия в ПО промежуточного слоя:

# middleware.py 
def process_view(self, request, view_func, view_args, view_kwargs): 
    view_func.cls.my_attribute # 'something' 

Этот метод используется в Django REST Framework (https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/views.py#L94-L104)

Смежные вопросы