Композитный вид на основе класса Django

Я использую общие представления Django 1.3 на основе классов для проекта. Они действительно хороши, но я хотел бы быть СУХИМ. У меня есть страница, на которой отображается список материалов, которые мы получили в прессе, и другая, на которой отображается список статей, которые мы опубликовали. На странице обзора мне нужно отобразить оба списка. Я хотел бы создать составное представление, которое принимает оба представления и создает контекст с обоими прикрепленными наборами запросов.


person Kenzic    schedule 21.04.2011    source источник
comment
Вместо того, чтобы обновлять свой пост, вы должны ответить на свой вопрос. Таким образом, сообщество может с первого взгляда определить, есть ли решение и какое оно есть.   -  person Dave    schedule 26.09.2011
comment
Когда я начал работать с Django, я обнаружил, что универсальные представления подходят почти для всего. Я изменил, исправил и исправил это, чтобы делать то, что я хотел. Проблема была в том, что это не то, что они решают. Как только вы переступите границы того, для чего они предназначены, просто используйте вместо них обычный вид.   -  person Emil Stenström    schedule 04.10.2011
comment
@Dave Я переместил решение Кензика в ответ и пометил ответ в надежде, что модераторы припишут его Кензику, а не мне.   -  person akaihola    schedule 28.11.2011


Ответы (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,)

    ]
person akaihola    schedule 28.11.2011
comment
Если вы не хотите зарабатывать репутацию в результате чьего-то ответа, то вы можете переключить его на CW. Кроме того, прошло два месяца, а Кензич не создал ответа; разумно, чтобы другие вмешались и дали правильный ответ. - person casperOne; 28.11.2011

На мой взгляд, представление — это просто одна страница. Представление может иметь несколько форм, что, на мой взгляд, является лучшим решением в вашем примере.

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

Ваше решение в основном похоже на фреймы, но на сервере, а не в браузере.

person Some programmer dude    schedule 21.10.2011

Простой способ:

Не используйте общее представление и объект paginator вручную для обоих наборов запросов.

Это не будет так долго, и это не какие-то строчки, которые убьют ваше СУХОЕ ИМО.

Общий, но долгий путь:

Создайте представление, объединяющее методы __init__ и get_context для передачи аргумента двум экземплярам ListView.

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

get_context следует вызывать оба метода экземпляров get_context Listview и объединять их в один объект контекста.

Обязательно настройте разные template_object_name для каждого ListView, чтобы они не переопределяли друг друга в контекстном словаре.

Сделайте это общим способом и не забудьте опубликовать свой код на djangosnippet :-)

person e-satis    schedule 26.11.2011

Может быть, вы можете переопределить метод 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 }}.

person iJK    schedule 26.04.2011