简短版:
是否有一种简单的内置方法来识别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发布了“否”:)再次感谢大家。
答案 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 %}
加特