我是django的新手,我想知道在模板中包含视图(包含某些逻辑及其生成的HTML)的最佳/推荐方法是什么。
我的具体例子如下: 我有一个模型:
class City(models.Model):
name = models.CharField(max_length=200)
class Place(models.Model):
city = models.ForeignKey(City)
name = models.CharField(max_length=200)
state = models.IntegerField()
所以我需要一个视图来显示每个城市和它的位置。每个地方都应根据其状态以不同的方式呈现。每种不同的方式都非常不同,可能需要一些商业逻辑。
根据我对其他框架的经验,我想象如下。从使用城市模板调用将呈现位置的视图,该视图将具有所有必需的逻辑,并将选择用于呈现场所的模板: 示例伪代码:
cities.html
{% for place in places %}
{% include_view 'show_place' place %}
{% endfor %}
include_view标记会调用一个视图,该视图将决定在给定位置使用哪个模板:
def show_place(request, place):
# Here I will probably use more logic to prepare the template.
template_name = "places/default.html"
if place.state == 1 :
template_name = 'places/active.html'
if place.state == 2 :
template_name = 'places/started.html'
if place.state == 3 :
template_name = 'places/completed.html'
# etc
return render(request, template_name, { 'place': place } )
这种方法在django中是否可行?
我看到了使用像这样的包含标签的可能性:Include a view in a template或 Template includes and django views/urls. How (do/should) they work?
但这会强制使用固定模板注册自定义模板函数: register.inclusion_tag('results.html')(show_results)#here我需要逻辑,并使'results.html'动态化。
此外,我希望将show_place作为普通视图,以便能够直接访问它。
我也可以在IF中询问模板中的状态并使用{%include%}标记,但这样我就可以在视图中使用其他方法中的其他业务逻辑:
{% for place in places %}
{% if place.state = 1 %}
{% include 'places/active.html' %}
{% if ... }
{% include ... }
{% endfor %}
实现这一目标的最佳方法是什么?
谢谢!
答案 0 :(得分:4)
您需要使用的是Django Custom Template Tag。您只需在模板中将变量传递给它,然后让它决定在当前模板中插入哪个视图和模板。
一个例子:
您的自定义模板标记(rend_item.py)
def return_template(item):
template = 'null'
context = {
#Dictionary of things to pass back
}
#if statements that choose what 'template' should be
if item == 5:
template = 'item5.html'
else:
template = 'default.html'
#render the template
return render_to_string(template, context)
模板
{# Make sure you load the py file where your template tag is located at the top #}
{% load rend_item %}
{% for item in cart %}
{{ item|return_template }}
{% endfor %}
答案 1 :(得分:0)
即使不久前又问了这个问题,我仍在搜索相同的功能。
我相信我找到了第一个问题的答案,也找到了JcKelly帖子的后续问题->“将过滤器作为实际视图”(我认为过滤器意味着渲染)。
我在网上找到了以下代码段(是自定义模板标签,请参阅JcKelley上的自定义模板标签信息)
https://djangosnippets.org/snippets/1568/
对我来说已经过时了。因此,我遵循了它的方法并提出了:
您的TemplateTag.py文件
from django.template import Library, Node, Variable, TemplateSyntaxError
from django.conf import settings
from django.urls import reverse, resolve, NoReverseMatch
register = Library()
class ViewNode(Node):
def __init__(self, url_or_view, args, kwargs):
self.url_or_view = url_or_view
self.args = args
self.kwargs = kwargs
def render(self, context):
if 'request' not in context:
raise TemplateSyntaxError("No request has been made.")
url_or_view = Variable(self.url_or_view).resolve(context)
try:
view, args, kwargs = resolve(reverse(url_or_view))
except NoReverseMatch:
view, args, kwargs = resolve(url_or_view)
try:
if callable(view):
self.args += args
self.kwargs.update(**kwargs)
return (view(context['request'], *self.args, **self.kwargs)
.rendered_content)
raise "%r is not callable" % view
except:
if settings.DEBUG:
raise
return None
@register.tag(name='view')
def do_view(parser, token):
args, kwargs, tokens = [], {}, token.split_contents()
if len(tokens) < 2:
raise TemplateSyntaxError(
f"{token.contents.split()[0]} tag requires one or more arguments")
for t in tokens[2:]:
kw = t.find("=")
args.append(t) if kw == -1 else kwargs.update({str(t[:kw]): t[kw+1:]})
return ViewNode(tokens[1], args, kwargs)
您的Template-file.html ->使用示例
使用视图的路径名, (有关路径名的信息,请参见https://docs.djangoproject.com/en/2.2/topics/http/urls/#naming-url-patterns ):
{% view "mymodule:inner" %}
{% view "mymodule:inner" "value" %}
{% view "mymodule:inner" keyword="value" %}
{% view "mymodule:inner" arg_expr %}
{% view "mymodule:inner" keyword=arg_expr %}
使用URL(或可评估为URL的内容)
{% view "/inner" %}
{% view url_expr %}
希望这可能对某人有所帮助!