【问题标题】:Django: What is the best way to serve several views of the same data, preferably rendered differently for each?Django:为相同数据的多个视图提供服务的最佳方式是什么,最好为每个视图提供不同的呈现方式?
【发布时间】:2011-05-27 15:36:42
【问题描述】:

有可能吗?

我的问题是,我的主页上有几列,所有这些列都需要显示使用不同过滤器的模型,以及不同的模型。我不想获取模型并在视图中对其进行过滤,然后将它们作为变量传递给包含所有“model1_filterAppliedA”、“model1_filterAppliedB”的主页。这似乎有点矫枉过正。我想要一个很好的方式来说“在此列中显示此模型的此过滤查询集”“在另一列中使用此过滤器显示此其他查询集”。

在 django 中实现这一目标的最佳方法是什么?

谢谢

编辑:

所以经过一段时间的实验;

选项 1:

我有一个看起来像这样的模板标签

@register.inclusion_tag('app/accordion_column.html', takes_context=True)
def accordion_by_filter(context, f):
    user = context['request'].user
    print "f: " + str(f)

    filetered_mobjects = Modell.objects \
                            .filter(creator=user.userprofile) \
                            .filter(state=f) \
                            .order_by('-created')[0:10]

    return {'mobjects': filetered_mobjects}

然后从我的模板中调用它

{% load mytags %}
{% accordion_by_filter 'A' %}

并且手风琴_column.html 扩展了我的其他模板并且只是循环遍历mobjects。 现在,当我需要在 main_column 中显示所有 mobjects 但由 'B' 过滤时,我会做同样的事情,但用accordion_by_filter 'B' 调用它

所以对于索引视图,它具有手风琴列(左侧)main_column 和 right_sidebar。对于要应用的每个过滤器,将对数据库进行三个单独的命中。我认为这没问题,因为另一种选择是获取所有 mobjects 并在结果列表中过滤?

选项 2;过滤器,加载任何模板的视图应该获取所有或一些模型,并将其在变量中铲到模板中,然后通过模板过滤器像普通列表一样过滤。所以这应该是一次访问数据库但结果会更重,并且它的过滤将在模板过滤器中计算多次,而不是告诉数据库这样做。

过滤器:

@register.filter def state(mobjects_list, arg):

filtered = []
for p in mobjects_list:
    if p.state == arg:
        filtered.append(p)

return filtered

在视图返回我可以做的 mobjects 的任何模板中

for p in mobjects|state:'A'
    ....

哪个选项更可取,最快?

【问题讨论】:

    标签: django model-view-controller templates views django-templates


    【解决方案1】:

    听起来上下文处理器就是你想要的。基本上,您可以编写一个上下文处理器,为每个 RequestContext 添加一些上下文。上下文处理器可能看起来像这样(我通常将它们放在文件 project_directory/app_directory/context_processors.py 中):

    from project.app.models import Book
    
    def number_of_books(request):
        return {'num_books': Book.objects.all().count()}
    

    然后,在项目的 settings.py 中,将此文件添加到 TEMPLATE_CONTEXT_PROCESSORS 元组中:

    TEMPLATE_CONTEXT_PROCESSORS = ('app.context_processors.number_of_books', 'other', 'stuff')
    

    最后,您必须让所有视图函数都使用 RequestContext 而不是普通的旧 Context。通用视图自动使用 RequestContext。如果您使用的是 render_to_response,则必须添加一个 context_instance kwarg(此示例中的“名称”只是已在此视图中作为上下文传递的局部变量):

    from django.template import RequestContext
    
    def my_view(request):
        # ... some code, including assigning the 'name' variable to something ...
        return render_to_response("app/template.html", {'name': name},
                           context_instance=RequestContext(request))
    

    我最喜欢的确保我使用 RequestContext 的方法是使用 django-annoying 的 render_to 装饰器(方便的第三方集合):https://bitbucket.org/offline/django-annoying/wiki/Home

    现在,每次渲染模板时,它都会拥有来自其自身视图的所有正常上下文变量以及来自上下文处理器的上下文变量。在我的示例中,您的书店网站可能在每一页的页眉中都有一行写着“现在提供 3,141,592 本书!”假设您有一个名为 base.html 的基本模板,所有其他模板都扩展了它,您可以这样完成它:

    <div id="header">
      <h1> Cool Online Bookstore </h1>
      <p> Now offering {{ num_books }} books! </p>
    </div>
    

    【讨论】:

    • 所有上下文处理器每次RequestContext被实例化时运行,无论是否需要变量。如果他们总是查询数据库,这很快就会变得非常昂贵。
    • 我在过去的项目中考虑过这一点,但我从来没有真正遇到过由此产生的性能问题(并不是说我创建了任何高流量的网站)。例如,如果您需要一个带有大量来自数据库的最新信息的侧边栏,我不知道有更好或更便宜的方法来做到这一点。有没有更好的办法?显然,缓存会有所帮助,具体取决于您需要信息的最新程度。
    • 有趣的方法 baddox。我正在研究更多使用模板标签,但问题是我必须有一种重复,应用每个过滤器的每个标签,或者我提供一个字符串来过滤一个标签,但是标签将具有“逻辑” - 在哪里输出这些东西,到什么 sn-p。它增加了我不喜欢的各种并发症。但是第一种方法有重复,我也不喜欢。这种方法有点开销。它应该只在某个时候呈现。可以用模板过滤器完成吗?
    • 我没有创建模板标签或过滤器的经验(我只使用内置标签),但在我看来,模板不应该显式访问数据库,甚至不应该知道数据库事情的一面。上下文处理器确实存在每个RequestContext 实例化都会执行它们的问题,所以如果你想做繁重的数据库工作并且只在几页上显示它,它们可能不是要走的路。
    • 基于类的视图可以帮助减少代码重复,但我对这些也缺乏经验。它们计划在 Django 1.3 中正式发布,这里已经有文档:docs.djangoproject.com/en/dev/topics/class-based-views
    猜你喜欢
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    相关资源
    最近更新 更多