Django forms how to dynamically render fields in a loop - django

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

Related

Django Template rendering from for loop

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 %}

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 %}

Django: Why is form.id within a formset empty?

I came across a strange issue.
I create a regular formset and everything works as intended:
deal_formset = formset_factory(DealCForm, extra=0)
...
formset = deal_formset(data)
Within the template though I don't seem to get the id of the current form, which I am iterating through. why is form.id empty?
{{ formset.management_form }}
{% if formset %}
{% for form in formset %}
...
{{form.id}}
{% endfor %}
{% endif %}