Displaying forms in a template is rather easy in Django:
I have created and have been using gladly for about a year now my own generic templates. So, I wanted to share, here it is:
Creating a view is as simple as this:
class PersonDetail(DetailViewParent):
model=Person
DetailViewParent used above (override fields
and exclude
as needed; default is to include all):
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
Relevant part of the template:
{% fields %}
{% for name, label, value, is_link in fields %}
{{ label|capfirst }}
{% if value.get_absolute_url and request.is_ajax %}
{{ value }}
{% elif value.get_absolute_url %}
{{ value }}
{% else %}
{% if is_link and request.is_ajax %}
{{ value }}
{% elif is_link %}
{{ value }}
{% else %}
{{ value }}
{% endif %}
{% endif %}
{% endfor %}
And the template tags:
@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 ''
The template might be customized to your needs and liking. But I would like to note two things:
1) get_absolute_url
: if this (standard django) model method is defined, the field value is shown as url.
2) modal-loader
class: this triggers js on the client side to show the detail view in a bootstrap 3 modal. Furthermore, if clicked on a link as mentioned in 1) that is loaded onto the same modal, thus making it easier to browse detail views. It has also a "back" button to go back to the previous model's view. I am not including that here because it is a lot of code, and beyond the scope of this question.