Django类视图中如何将变量传递给模板

27

如果我有一个基于类的视图,就像这样:

class SomeView (View):
    response_template='some_template.html'
    var1 = 0
    var2 = 1

    def get(self, request, *args, **kwargs):
        return render_to_response(self.response_template, locals(), context_instance=RequestContext(request))

我的问题是,在模板some_template.html内,我如何访问var1var2?就我所理解的,locals()函数会将所有局部变量倒入到模板中,这个方法到目前为止一直很有效。但是这些其他变量并不是"局部的",它们属于一个类,那么我该如何传递它们呢?

谢谢!

5个回答

44

一种更加简洁的方法是复制 Django 的模板视图:

class TemplateView(TemplateResponseMixin, ContextMixin, View):
    """
    A view that renders a template.  This view will also pass into the context
    any keyword arguments passed by the url conf.
    """
    def get(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

然后将其添加到get_context_data函数中。或者您可以简单地使用TemplateView,它允许您指定模板名称,然后您可以重写get_context_data函数:

class SomeView(generic.TemplateView):
    var1 = 0
    var2 = 1 
    template_name = 'some_template.html'

    def get_context_data(self, **kwargs):
        context = super(SomeView, self).get_context_data(**kwargs)
        context.update({'var1': self.var1, 'var2': self.var2})
        return context

编辑

Django有通用视图,您可以将其用于各种事情,我强烈建议您查看文档以获取完整列表。这些通用视图具有函数,您可以覆盖它们以执行默认不支持的自定义操作。在您的情况下,您只需要一个带有上下文变量的模板,这意味着您可以子类化TemplateView并提供template_name,最后您可以覆盖get_context_data函数以添加您的上下文数据,这就是您所需的全部内容,您的情况下第二段代码就足够了。


我相信你所写的是一个好的解决方案,但我还不太理解它... Django 中有太多我还没有完全掌握的东西。这个框架有点复杂。 - reedvoid
我已经更新了我的答案,只是为了指引你在将来的使用中走向正确的方向 :) - CJ4

21

get方法中将self.var1self.var2添加到上下文中:

class SomeView (View):
    response_template='some_template.html'
    var1 = 0
    var2 = 1

    def get(self, request, *args, **kwargs):
        context = locals()
        context['var1'] = self.var1
        context['var2'] = self.var2
        return render_to_response(self.response_template, context, context_instance=RequestContext(request))
注意:render_to_response()在Django 3.0及以上版本中已被移除(请改用render())。
另外,我不确定将locals()作为模板上下文传递是否是一种良好的实践。我更喜欢明确构造传递到模板中的数据=仅传递您在模板中真正需要的内容。

是因为locals()可能包含很多随机的东西,可能会污染模板中的命名空间吗?引入一堆我永远不会使用的东西?还是出于其他原因?安全性? - reedvoid
1
正如Python之禅所说:“显式优于隐式”。我认为这样做不仅更加清晰易懂,而且更容易调试。 - alecxe
3
我同意使用locals()是不好的做法。你可以明确地使用get_context_data()重写来实现,这在基于类的视图中被认为是向模板传递变量的标准方式。 - Aaron Beals
render_to_response()在Django 3.0中已被移除。如果您正在使用Django 3.0或更高版本,则应使用render()。 - ahmadkarimi12

6

您可以在这里看到两种方法。第一种方法是,您可以像这样声明一个名为get_context_data的函数:

def get_context_data(self, **kwargs):          
    context = super().get_context_data(**kwargs)                     
    new_context_entry = "here it goes"
    context["new_context_entry"] = new_context_entry
    return context

如果您使用Django 2.x,还需在get_context_data中传递*args参数。
第二种方法是在视图中的某个函数中修改extra_context变量。
self.extra_context["another_one"] = "here goes more"

这在Django 4上不起作用。在View基类中没有extra_context。 - undefined
谢谢 @max。我已经更新了答案。 - undefined

0

如果想在函数中传递类标签变量,需要使用self进行引用,它代表一个新创建的对象。我们知道,在类中访问任何变量都需要引用其对象。否则,会出现全局名称“your variable”未定义的错误。

例如,在您的情况下,可以这样做:

class YourView(genericView):
    template_name='your_template.html'
    var1 = 12
    var2 =1

    def get(self, **kwargs):
        context = locals()
        context['var1'] = self.var1
       context['var2'] = self.var2
       return context

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接