Расширение общих классов представлений для общих get_context_data

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

def get_context_data(self, **kwargs):
    # Call the base implementation first to get a context
    context = super(MyListView, self).get_context_data(**kwargs)
    # Add in the house
    context['house'] = self.get_object().house
    return context

Поскольку я не люблю повторяться, я подумал, что могу создать новый класс, расширяющий представление, а затем основывать все свои представления на новом расширенном классе представления. Дело в том, что я использую 4 класса представлений: CreateView, UpdateView, ListView и DeleteView. Мне действительно нужно создать новый класс для каждого из них?

Разве нет чего-то вроде «базового» класса представления django? Может быть, более разумный способ сделать это? Спасибо заранее!


person Clash    schedule 26.04.2012    source источник
comment
Это потенциальное решение, хотя я не уверен, что оно меня полностью устраивает - reinout.vanrees.org/weblog/2014/05/19/context.html   -  person rix    schedule 20.05.2014


Ответы (1)


Создайте миксин:

from django.views.generic.base import ContextMixin

class HouseMixin(ContextMixin):
  def get_house(self):
    # Get the house somehow
    return house

  def get_context_data(self, **kwargs):
    ctx = super(HouseMixin, self).get_context_data(**kwargs)
    ctx['house'] = self.get_house()
    return ctx

Затем в других ваших классах вы использовали бы множественное наследование:

class HouseEditView(HouseMixin, UpdateView):
  pass

class HouseListView(HouseMixin, ListView):
  pass

и так далее, то все эти представления будут иметь house в контексте.

person Jj.    schedule 26.04.2012
comment
Вау, это действительно сработало! Я думал, что super(HouseMixin, self).get_context_data(**kwargs) вернет ошибку, потому что super для HouseMixin является объектом, а объект не определил get_context_data. Можете ли вы объяснить мне, почему это работает? - person Clash; 26.04.2012
comment
Он работает до тех пор, пока один из родительских классов реализует метод, иначе он вызовет ошибку. Таким образом, этот миксин предназначен для смешивания с любым представлением Django, которое также реализует .get_context_data(). - person Jj.; 26.04.2012
comment
это связано с порядком расширения классов? то есть HouseMixin, UpdateView вместо UpdateView, HouseMixin - person Clash; 26.04.2012
comment
Да, порядок родительских классов влияет на MRO, прочитайте ответ SO со ссылкой на его историю здесь: stackoverflow.com/a/3277407 /43490 - person Jj.; 26.04.2012
comment
У меня были проблемы с примесями и реверсированием URL-адресов, пока я не изменил порядок аргументов в определениях классов, например. class MyListView(ListView, BaseContextMixin):. Джанго 1.5.5, Питон 2.7.5. - person Geradlus_RU; 12.11.2013
comment
Что, если get_house() — это метод, зависящий от request? Например, если бы мне нужно было получить экземпляр дома на основе request.user? - person Algorithmatic; 07.06.2016
comment
Неважно, я понял. Вам просто нужно сделать class HouseMixin(ContextMixin, View) внутри - person Algorithmatic; 07.06.2016