Я использую общие представления Django 1.3 на основе классов для проекта. Они действительно хороши, но я хотел бы быть СУХИМ. У меня есть страница, на которой отображается список материалов, которые мы получили в прессе, и другая, на которой отображается список статей, которые мы опубликовали. На странице обзора мне нужно отобразить оба списка. Я хотел бы создать составное представление, которое принимает оба представления и создает контекст с обоими прикрепленными наборами запросов.
Композитный вид на основе класса Django
Ответы (4)
Kenzic смог добиться этого, выполнив следующие действия:
composite.py:
from django.views.generic.base import TemplateResponseMixin, View
class BaseCompositeView(TemplateResponseMixin, View):
composite_views = []
def get_composite_views(self):
return self.composite_views
def get_context_data(self, request, *args, **kwargs):
context = {}
composite_views = self.get_composite_views()
for composite_view in composite_views:
cls = composite_view[0]
try:
clsview = cls.as_view(**composite_view[1])
except IndexError:
clsview = cls.as_view()
view = clsview(request, *args, **kwargs)
context_data = view.context_data
context.update(context_data)
return context
def get(self, request, *args, **kwargs):
context = self.get_context_data(request, *args, **kwargs)
return self.render_to_response(context)
views.py:
from django.views.generic import TemplateView, ListView, DetailView
from composite import BaseCompositeView
from .models import *
class MediaCoverageList(ListView):
queryset = MediaCoverageItem.objects.order_by('-date')
class PressKitList(ListView):
queryset = PressKit.objects.all()
class NewsroomLanding(BaseCompositeView):
template_name = 'newsroom/landing.html'
composite_views = [
(MediaCoverageList,{
'paginate_by': 10,
},),
(PressKitList,)
]
На мой взгляд, представление — это просто одна страница. Представление может иметь несколько форм, что, на мой взгляд, является лучшим решением в вашем примере.
Просто разделите шаблон на несколько файлов, где каждая форма имеет небольшой шаблон, и используйте директиву включения шаблона, чтобы соединить их вместе. Это также имеет дополнительное преимущество, заключающееся в том, что форму можно очень просто повторно использовать в других представлениях.
Ваше решение в основном похоже на фреймы, но на сервере, а не в браузере.
Простой способ:
Не используйте общее представление и объект paginator вручную для обоих наборов запросов.
Это не будет так долго, и это не какие-то строчки, которые убьют ваше СУХОЕ ИМО.
Общий, но долгий путь:
Создайте представление, объединяющее методы __init_
_ и get_context
для передачи аргумента двум экземплярам ListView.
init должен создавать экземпляры обоих ListView
, передавать параметры и добавлять экземпляры к атрибутам оболочки.
get_context
следует вызывать оба метода экземпляров get_context Listview и объединять их в один объект контекста.
Обязательно настройте разные template_object_name
для каждого ListView
, чтобы они не переопределяли друг друга в контекстном словаре.
Сделайте это общим способом и не забудьте опубликовать свой код на djangosnippet :-)
Может быть, вы можете переопределить метод get_context_data, чтобы добавить дополнительные данные в контекст?
def get_context_data(self, **kwargs):
context = super(AuthorListView, self).get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['press_list'] = Press.objects.all()
context['articles_list] = Article.objects.all()
return context
и в вашем шаблоне вы можете получить список прессы и список статей, используя {{ press_list }}
и {{ articles_list }}
.