Django:如何从模板中识别调用视图?

时间:2009-04-27 06:17:30

标签: django

简短版:

是否有一种简单的内置方法来识别Django模板中的调用视图,而不传递额外的上下文变量?

长(原创)版本:

我的一个Django应用程序有几个不同的视图,每个视图都有自己的命名URL模式,它们都呈现相同的模板。根据被调用的视图,需要更改的模板代码非常少,太小而不值得为每个视图设置单独的模板的开销,所以理想情况下我需要找到一种方法来识别模板中的调用视图

我已经尝试设置视图以传递额外的上下文变量(例如“view_name”)以识别调用视图,我也尝试使用{% ifequal request.path "/some/path/" %}比较,但这些解决方案似乎都不是特别明显优雅。有没有更好的方法从模板中识别调用视图?有没有办法访问视图的名称或URL模式的名称?


更新1:关于这只是我误解MVC的评论,我理解MVC,但是Django's not really an MVC framework。我相信我的应用程序的设置方式与Django对MVC的看法一致:视图描述显示哪些数据,模板描述 数据的呈现方式。我碰巧有许多视图准备不同的数据,但都使用相同的模板,因为所有视图的数据呈现方式相同。我只是想找一种简单的方法来识别模板中的调用视图(如果存在的话)。

更新2:感谢您的所有答案。我认为这个问题正在被推翻 - 正如我在原来的问题中所提到的,我已经考虑并尝试了所有建议的解决方案 - 所以我现在把它提炼成一个“短版本”,现在问题的顶部。而现在似乎如果有人只是发布“否”,那么这将是最正确的答案:)

更新3: Carl Meyer发布了“否”:)再次感谢大家。

10 个答案:

答案 0 :(得分:22)

自Django 1.5起,url_name可以使用:

访问
request.resolver_match.url_name

在此之前,您可以使用中间件:

from django.core.urlresolvers import resolve

class ViewNameMiddleware(object):  
    def process_view(self, request, view_func, view_args, view_kwargs):
        url_name = resolve(request.path).url_name
        request.url_name = url_name

然后在MIDDLEWARE_CLASSES中添加它,在模板中我有:

{% if request.url_name == "url_name" %} ... {% endif %}

考虑到RequestContext(请求)总是传递给render函数。我更喜欢使用url_name作为url,但是可以使用resolve()。app_name和resolve()。func.name,但这不适用于装饰器 - 而是返回装饰器函数名称。

答案 1 :(得分:18)

不,这不是一个坏主意。要从模板直接引用视图函数名称,会在视图层和模板层之间引入过度紧密的耦合。

更好的解决方案是Django的模板继承系统。定义一个公共父模板,其中包含需要在每个视图版本中更改的(小)区域的块。然后定义每个视图的模板以从父级扩展并适当地定义该块。

答案 2 :(得分:2)

自Django 1.5起,您可以通过ResolverMatch访问request.resolver_match的实例。

ResolverMatch为您提供已解析的网址名称,命名空间等。

答案 3 :(得分:2)

如果您的urls.py和views.py的命名保持一致,则将返回视图名称:

{{ request.resolver_match.url_name }}

在模板中调用它时,请确保对其应用一些上下文。例如,我在这里使用它从详细信息视图中删除删除按钮,但是在我的更新视图中,删除按钮仍然会出现!

{% if request.resolver_match.url_name != 'employee_detail' %}

答案 4 :(得分:1)

这听起来像是您可以设置的通用视图的完美示例。

请参阅以下资源:

这些链接可以帮助您相应地简化视图和模板。

答案 5 :(得分:1)

我正在为帮助页面系统工作,我希望每个视图对应于我的cms中的帮助页面,如果没有为该视图定义帮助页面,则显示默认页面。我偶然发现this blog他们使用模板上下文处理器和一些python检查魔法来推断视图名称并用它填充上下文。

答案 6 :(得分:0)

一个简单的解决方案是:

def view1(req):
   viewname = "view1"
   and pass this viewname to the template context   

def view2(req):
   viewname = "view2"
   and pass this viewname to the template context   
模板中的

访问视图名称为

{{viewname}} 

并且您也可以在比较中使用它。

答案 7 :(得分:0)

大多数通用视图(如果不是全部)都会继承ContextMixin,它会添加一个指向View实例的view上下文变量。

答案 8 :(得分:0)

如果您使用的是基于类的视图,则很可能会有一个view变量可以访问。

您可以使用几种方法来确定调用了哪个视图或正在渲染哪个模板。

例如

{% if view.template_name == 'foo.html' %}
# do something
{% else %}
# other thing
{% endif %}

另一种选择是取出需要更改的模板部分,并将其制作为代码段,然后在模板中使用{% include 'my_snippet.html' with button_type = 'bold' %},向该代码段发送任意值,以便确定要删除的内容。显示/如何设置样式。

答案 9 :(得分:-1)

为什么不尝试设置会话cookie,然后从模板中读取cookie。

在您的观看设置Cookie

def view1(request):
 ...
#set cookie
 request.session["param"]="view1"

def view2(request):
  request.session["param"]="view2"


then in your ONE template check something like..

{% ifequal request.session.param "view1" %}
   ... do stuff related to view1
{% endifequal %}

{% ifequal request.session.param "view2" %}
  ... do stuff related to "view2"
{% endifequal %}

加特