在Django中显示模板中的表单非常简单:
<form action="" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Update" />
</form>
基本上只有一个词 - 显示{{ form }}
。它非常简单,您可以为不同的表单使用相同的模板。
如果您使用的是CBV,如CreateView或UpdateView,则可以使用fields = []
列表限制表单上显示的字段。
与此并行绘制,人们期望有一个类似的工作流程来显示模型(而不是编辑),例如在DetailView中。但是,没有这样的东西..你必须为你使用的每个DetailView编写一个自定义模板。如:
<h3>User: {{ user }}</h3>
<label>First Name</label>: {{ user.first_name }} <br />
<label>Last Name</label>: {{ user.last_name }} <br />
<label>Username</label>: {{ user.username }} <br />
<label>School</label>: {{ user.person.school.name }} <br />
这与{{ form }}
生成的内容非常相似,除了此处打印的字段值,而不是input
在那里打印。
所以,我想知道,为什么还没有针对DetailView的可重复使用的通用模板?对此有技术限制,还是不像我想象的那样可重复使用?
答案 0 :(得分:3)
我认为它不像你想象的那样可重复使用。
可以想象,可以定义&#34;标准&#34;渲染简单模型属性(如CharField
)的方法 - 当您进入更复杂的关系字段(如ManyToManyField
,ForeignKey
,OneToOneField
时,这很快就变得不可能了。除了最简单的模型之外,您最终会快速覆盖任何默认表示。
其次,Django不是 - 也不应该 - 对你的模型的用途持主观态度,因此它没有尝试假设你想要如何呈现它们。
这与在Django和HTML中定义单个表单字段的结构的表单不同,并且两者之间存在很强的相关性。
答案 1 :(得分:3)
我已经创建并且已经使用了大约一年,现在我自己的通用模板。所以,我想分享,这里是:
创建视图就像这样简单:
class PersonDetail(DetailViewParent):
model=Person
上面使用的DetailViewParent(根据需要覆盖fields
和exclude
;默认包含所有):
class DetailViewParent(DetailView):
fields=[]
exclude=[]
template_name='common/modal_detail.html'
def get_context_data(self, **kwargs):
context=super(DetailViewParent, self).get_context_data(**kwargs)
context['exclude']=self.exclude
context['fields']=self.fields
return context
模板的相关部分:
{% fields %}
{% for name, label, value, is_link in fields %}
<tr>
<td><strong>{{ label|capfirst }}</strong></td>
<td>
{% if value.get_absolute_url and request.is_ajax %}
<a class="modal-loader" href="{{ value.get_absolute_url }}">{{ value }}</a>
{% elif value.get_absolute_url %}
<a href="{{ value.get_absolute_url }}">{{ value }}</a>
{% else %}
{% if is_link and request.is_ajax %}
<a class="modal-loader" href="{{ value }}">{{ value }}</a>
{% elif is_link %}
<a href="{{ value }}">{{ value }}</a>
{% else %}
{{ value }}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
模板标签:
@register.tag(name="fields")
def generate_fields(parser, token):
"""
{% fields %} - loads field name, label, value, is_link to the context
"""
args=token.contents.split()
object_name='object'
if len(args) == 2:
object_name=args[1]
return FieldsNode(object_name)
class FieldsNode(template.Node):
"""
called by generate_fields above
"""
def __init__(self, object_name):
self.object_name=object_name
def render(self, context):
# Get the data necessary for rendering the thing, and add it to the context.
try:
obj=template.Variable(self.object_name).resolve(context)
except template.VariableDoesNotExist:
return ''
include_fields=context.get("fields", None)
exclude_fields=context.get("exclude", None)
fields=[]
for field in obj._meta.fields:
name=field.name
if exclude_fields and name in exclude_fields:
continue
if include_fields and name not in include_fields:
continue
label=field.verbose_name
value=getattr(obj, field.name)
is_link=(type(field).__name__ in ('URLField',))
if isinstance(value, bool):
value=get_bool_check_mark(value)
elif value is None:
value=''
fields.append((
name, label, value, is_link,
))
# If include_fields was defined, then sort by the order.
if include_fields:
fields=sorted(fields, key=lambda field_: include_fields.index(field_[0]))
context['fields']=fields
return ''
模板可根据您的需求和喜好进行定制。但我想指出两件事:
1)get_absolute_url
:如果定义了此(标准django)模型方法,则字段值显示为url。
2)modal-loader
class:这会触发客户端的js以在bootstrap 3模式中显示详细视图。此外,如果点击1)中提到的链接加载到同一模态上,则可以更轻松地浏览详细视图。它还有一个&#34; back&#34;按钮返回上一个模型的视图。我不是在这里包括它,因为它是很多代码,超出了这个问题的范围。