Django Template rendering from for loop - django

I have a simple form with a field names as company_name, location, country and few more which I am rendering from views.py as {'form':form}.
The usual way to call the form on the template is {% for field in form %} which is rendering the fields in the order of field attribute in the form.py file. Another way to add special classes and styles to each field I am calling every field with name as {{ form.company_name }}.
I have a another for loop which only contains the names of the form fields {% for element in fieldnames %}.
I want to render the form field as per the order in the fieldnames. I tried allot with the below example but not working.
{% for element in fieldnames %}
{{ form.element }}
{% endfor %}
Why cant we render like above using for loop but if I replace element name with the field name like {{ form.company_name }} its working

{% for name in fieldnames %}
{% for field in form %}
{% if field.name == name %}
{{ field }}
{% endif %}
{% endfor %}
{% endfor %}

Related

Accessings fields directly in Django adminform template?

I have a ton of fields that I need to layout (reorder) in a specific way the form (with some other extra html stuff). I created change_form.html file for my model, which itself works.
The problem is all examples are looping over the fields, I just want to refer to each field by name.
# this works
{% for fieldset in adminform %}
{% for line in fieldset %}
{% for field in line %}
<p>{{ field.field }}</p>
{% endfor %}
{% endfor %}
{% endfor %}
I know you can customise the admin.ModelAdmin with fieldsets, etc.. But that's not what I want.
I was trying different ways like below, but it doesn't work:
# assuming the admin model has the fields: first_name & last_name
{% block content %}
<!-- doesn't work !!! ->
{{ adminform.fieldsets.0.1.fields.first_name.field }}
{{ adminform.fieldsets.0.1.fields.last_name.field }}
<!-- neither does this -->
{{ adminform.fields.first_name.field }}
{{ adminform.fields.last_name.field }}
{% endblock %}
Now this doesn't work, is there any efficient way to directly access the fields I need?
I was looking in the complete wrong direction. Its actually super simple, you can use it as follows.
When you have model with a field last_name you can access the field:
# change_form.html (custom)
{% extends "admin/change_form.html" %}
{% block field_sets %}
# get the label
<label for="{{ adminform.form.last_name.label }}">
{{ adminform.form.last_name.id_for_label }}
</label>
# get the html widget
{{ adminform.form.last_name }}
# get the field value
{{ adminform.form.last_name.value }}
# create your own input (without the label)
<input name="{{ adminform.form.last_name.html_name }}">
# some other fields you can reference
{{ adminform.form.last_name.max_length }}
{{ adminform.form.last_name.required }}
{{ adminform.form.last_name.help_text }}
{{ adminform.form.last_name.label_suffix }}
{% endblock %}
U can create a ModelForm to be used in your ModelAdmin, check de docs -> https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
another way could be setting fields tuple, docs here -> https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fields
Hope this drives U in the right path.

Django forms how to dynamically render fields in a loop

Let's say I have a form with some fields. Some of those fields are units of measurements:
['quantity_units', 'weight_units', 'dimension_units']
I also have these fields:
['quantity', 'weight', 'dimension']
I would like to display the unit of measurement right beside the field:
Quantity: ___________________ _______<unit of measurement drop-down list>______
I thought I should first loop through the form's fields. For each iteration through the form's fields, I would check if the field name is in the units_list, if it is, then I would render the field and its unit field like so:
{% for field in form %}
{% for field_name in units_fields %}
{% if field.name in field_name %}
{{ field|add_class:"site-form-control" }} {{ form.field_name}}
{% else %}
{% ifchanged %}
{{ field|add_class:"site-form-control" }}
{% endifchanged %}
{% endif %}
{% endfor %}
{% endfor %}
This does not render the unit of measurement field with the drop-down list widget.
Any ideas how to fix this?
Edit:
I noticed that for some reason, Django displayed the {{ field }} twice and did not display {{ form.field_name }}. To manually choose the field, I wrote a template filter to get the value given the key for a dictionary. Then, I used it on the {{ form.fields }} which is an orderedDict
{% for field_name in units_fields %}
{% if field.name in field_name %}
{{ form.fields|dict_key:field_name }}
{% else %}
{% ifchanged %}
{{ field|add_class:"site-form-control" }}
{% endifchanged %}
{% endif %}
{% endfor %}
This renders the text representation of the field I want:
<django.forms.fields.ChoiceField object at 0x000001E5F35F3C18>
Any help to convert this text to an actual field is appreciated
The way I solved this was to write a simple tag that returns a boundfield object <django.forms.boundfield.BoundField object at 0x0000025 instead of <django.forms.fields.ChoiceField object at 0x000001E5F35F3C18>
#register.simple_tag(takes_context=True)
def get_form_field(context, form, field_name):
''' Given a form and a field_name, it returns form.field'''
try:
field = form[field_name]
except KeyError:
field = None
return field

Django accessing form fields dynamically in template

I am trying to mimic the django admin's fieldsets functionality, to group form fields in my own view.
So I have a form in my template, and I have passed the fieldset list in my context data.
{% for fieldset in fieldsets %}
<fieldset class="module aligned">
<h2>{{ fieldset.0 }}<h2>
{% for field in fieldset.1.fields %}
<div>
{{ form.field }}
</div>
{% endfor %}
</fieldset>
{% endfor %}
The problem is the {{ form.field }} is treating field as a string, and not as the value stored in the variable. Is there a way to access this in the template, like getattr().

django templates: How to know form field type and add any buttons based on field type

I am displaying my django forms dynamically with below code.
{% for field in form %}
{% if field.field.required %}
<span class="red">*</span>
{% endif %}
{{ field.label }}:
{{ field }}
{% endfor %}
Now I want to know the datatype of fields.if field type is Datetimeinput then I want give one button beside to it to get JavaScript calender.
i want do like as below but I am not able get it
{% for field in form %}
{% if field.field.required %}
<span class="red">*</span>
{% endif %}
{% if field.field_type == 'Datetimeinput' %}
{{ field.label }}:
{{ field }}
<label>From :</label><input type="text" name="from1" class="txtbox"><input type="button" value="Cal" onclick="displayCalendar(document.forms[0].from1,'yyyy-mm-dd',this)">
{% else %}
{{ field.label }}:
{{ field }}
{% endif %}
{% endfor %}
Help me out thanks in advance.
Make a template tag. Depending on Get type of Django form widget from within template. I used this solution once or twice.
from django import template
register = template.Library()
#register.filter('klass')
def klass(ob):
return ob.__class__.__name__
In template:
{{ field.field.widget|klass }}
Will return field class name to be used in your if statements.
You could write a custom template filter for that.
#register.filter
def fieldtype(obj):
return obj.__class__.__name__
Docs on custom filters: link
However, why not just render fields without looping over them?
{{ form.birthdate }}
Then you'll know for sure what is what.

how do I know I am dealing with the extra (empty) form within a formset?

deals_formset_factory = modelformset_factory(Deal, form=DealForm, extra=1)
formset = deals_formset_factory(queryset=query, prefix='deals')
{% for fs in formset.forms %}
{{ fs.id }}
{% endfor %}
While traversing through the forms of a formset, is it possible to find out which form contains instance data and which one is extra and hence empty?
You could check to see whether the form instance has a primary key. If it does, then it exists in the database. If it doesn't, then it's an extra form.
Untested code:
{% for form in formset.forms %}
{% if form.instance.pk %}
Form instance is saved in db
{% else %}
New instance
{% endif %}
{% endfor %}