【问题标题】:Django Class Based View Composite基于 Django 类的视图组合
【发布时间】:2011-08-10 16:08:34
【问题描述】:

我正在为一个项目使用 Django 1.3 的基于类的通用视图。他们真的很好,但我想成为 DRYer。我有一个页面显示我们收到的新闻报道列表,另一个页面显示我们已发布的文章列表。在概述页面上,我需要显示两个列表。我想创建一个复合视图,它接受两个视图并创建一个附加了两个查询集的上下文。

【问题讨论】:

  • 您应该回答自己的问题,而不是更新您的帖子。这样社区就可以一眼看出有解决方案,以及它是什么。
  • 当我开始使用 Django 时,我开始发现通用视图几乎可以作为所有工具。我修改、修补和修复了它以做我想做的事。问题是,这不是他们要解决的问题。一旦您超出了它们的用途限制,只需使用普通视图即可。
  • @Dave 我将 Kenzic 的解决方案移到了答案中并标记了答案,希望版主将其归因于 Kenzic 而不是我。

标签: django view composite django-class-based-views


【解决方案1】:

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

    ]

【讨论】:

  • 如果您不想因某人的回答而获得声望,那么您可以将其切换为 CW。此外,两个月过去了,肯齐奇还没有给出答案;其他人介入并提供正确答案是合理的。
【解决方案2】:

在我看来,视图只是一页。一个视图可以有多种形式,我认为在您的示例中这是一个更好的解决方案。

只需将模板拆分为多个文件,其中每个表单都有一个小模板,然后使用模板包含指令将其拼接在一起。这还有一个额外的好处,即表单可以非常简单地在其他视图中重用。

您的解决方案基本上类似于框架,但在服务器上而不是在浏览器中。

【讨论】:

    【解决方案3】:

    简单的方法:

    不要在两个查询集上手动使用通用视图和 paginator 对象。

    不会那么长,也不是一些台词会杀死你的 DRY IMO。

    通用但漫长的道路:

    创建一个包含 __init__ 和 get_context 方法的视图,以将参数传递给两个 ListView 实例。

    init 应该实例化ListView,传递参数并将实例添加到包装器的属性中。

    get_context 应该调用两个 get_context Listview 实例方法,并将它们合并到一个上下文对象中。

    确保为每个ListView 设置不同的template_object_name,这样它们就不会在上下文字典中相互覆盖。

    以通用方式执行此操作,并且不要忘记在 djangosnippet 上发布您的代码 :-)

    【讨论】:

      【解决方案4】:

      您是否可以重写 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 }} 获取新闻列表和文章列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-24
        • 2014-02-16
        • 2018-05-14
        • 2014-02-21
        • 2011-11-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多