Композитный вид на основе классов Django - PullRequest
13 голосов
/ 22 апреля 2011

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

Ответы [ 4 ]

4 голосов
/ 28 ноября 2011

Кензич смог сделать это, выполнив следующие действия:

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,)

    ]
0 голосов
/ 21 октября 2011

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

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

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

0 голосов
/ 26 ноября 2011

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

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

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

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

Создайте представление, которое обернет *Методы 1015 * _ и get_context для передачи аргумента двум экземплярам ListView.

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

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

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

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

0 голосов
/ 26 апреля 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 }}.

...