After reading over the Docs, and working with Django forms for quite a while, it would seem pretty standard to me that {{ form.as_p }} in the template would render a Django form. However, my situation is a bit different.
I have 2 checkboxes in my form:
class FORM(forms.Form):
field_a = forms.BooleanField(initial=False, label =('FIELD-A'))
field_b= forms.BooleanField(initial=True, label=('FIELD-B'))
I pass the form object as most would from the view:
context = {
'FORM':FORM(),
}
return render_to_string(template, context)
I am trying to use basic 'if' logic to see if I should display one, or both of the fields. I know most would say 'Just name them two separate forms', but I would prefer to keep them as one form for organization purposes.
THE PROBLEM
{% if BoolValue' %}
<form action='' method='post'>
{{ FORM.field_a }}
</form>
{% endif %}
This returns only the field, and not the field label (so just a checkbox). Going off of the Docs and other StackOverflow Questions, this should display the entire form, including the label, yet it doesn't.
These methods still work, however:
METHOD 1
{% for field in FORM%}
<div class="form">
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
This will display both forms, with their respective labels, and field inputs (checkboxes)
METHOD 2
{{ FORM.as_p }}
The traditional way of rendering the entire form will display both fields and labels, it is virtually identical to Method 1 in style and formatting.
EDIT
METHOD 3
{{ FORM.field_a.label_tag }} {{ Form.field_a }}
This will display the label and the form field. A possible work around, but I am looking for why {{ Form.field_a }} does not work on its own
So...
Why can I not render that individual form with its respective label? I am not looking for a work around so to speak, as I would like both fields to be under that one form. Any ideas?
Have you tried {{ FORM.field_a }} {{FORM.field_a.label_tag}}?
Related
I'm new in django. I try to create a simple form based on the model.
Imputs are displayed fine but i have problem with the labels.They don't appears on the page.
I can't figure out where is my mistake. For my it should be working fine.
Any idea what's is wrong here?
class RecForm (ModelForm):
class Meta:
model = Rec
fields = ['name', 'kind',]
labels = {
'name': 'Here put your name',
}
home.html
<form action="addrec" method="post">
{% csrf_token %}
{% for i in form %}
{{ i }}
<br><br>
{% endfor %}
<input type="submit" value="Submit">
{% endblock %}
You're rendering the field in your template as {{ i }}, with i being an instance of a BoundField (code). BoundField.__str__ calls widget.render (code) and returns the output. widget.render renders the value of of the widget's template (see widget templates here https://github.com/django/django/tree/4.0.2/django/forms/templates/django/forms/widgets). None of these templates include the label tag.
To render the label tag your should call {{ i.label_tag }} (code), which will render the tag with all attributes Django knows about. Extra attributes may require adjustments.
I have a modelformset that I want to save to a model.
In my templates, the following works perfectly (meaning that the form saves to the database when I hit submit):
{{ formset.management_form }}
{{ formset }}
Even this works great:
{{ formset.management_form }}
{% for row in formset %}
{{ row }}
{% endfor %}
But as soon as I want to style my formset (in a table) like so:
{{ formset.management_form }}
{% for row in formset %}
{{ row.field1 }}
{{ row.field2 }}
{{ row.field3 }}
{% endfor %}
I get [u'ManagementForm data is missing or has been tampered with'].
Fields 1 to 3 corresponds exactly to the model I want to save to. I really cannot figure this out!
My traceback shows this:
GET No GET data
POST Variable Value
form-0-field1 u'3'
form-0-field2 u'3'
form-0-field3 u'3'
Which are the same values I used in the first two examples (and which saved correctly).
Your rendering of the form doesn't include the additional data which are required for the ManagementForm (form-TOTAL_FORMS, form-INITIAL_FORMS and form-MAX_NUM_FORMS)
See: https://docs.djangoproject.com/en/1.7/topics/forms/formsets/#understanding-the-managementform
I finally found the answer (in the docs) that coincidently explains this matter exactly as I asked my question. The third option must render {{ row.id }}, otherwise Django will create the validation error. It is up to the user to use 'style="display: none;"' in the inline html, but it must be rendered.
Here's the link:
https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/#using-the-formset-in-the-template
Tested and it works!
I am using a formset and I want each from generated to display a numbered title for each unique form. So if I generate 5 forms, I want to have a text label display before the form fields that says "Form 1", "Form 2", ... "Form 5".
How do I:
Create a space in a form for such a plain informational text label?
Set the title for each form (I'm assuming in the template)?
Thanks!
You can put a label in template using forloop.counter before each form, something as below
<form method="post" action="">
{{ formset.management_form }}
<table>
{% for form in formset %}
<label> Form - {{forloop.counter}} </label>
{{ form }}
{% endfor %}
</table>
</form>
I realized the docs give the solution. You can access {{forloop.counter}} in the Layout and create a label using the HTML universal layout element:
Note that you can still use a helper (in this case we are using the
helper of the form used for building the formset). The main difference
here is that helper attributes are applied to the form structure,
while the layout is applied to the formset’s forms. Rendering formsets
injects some extra context in the layout rendering so that you can do
things like:
HTML("{% if forloop.first %}Message displayed only in the first form
of a formset forms list{% endif %}", Fieldset("Item {{ forloop.counter
}}", 'field-1', [...])
If I have a model that contains a ChoiceField with a RadioSelect widget, how can I render the radio buttons separately in a template?
Let's say I'm building a web app that allows new employees at a company to choose what kind of computer they want on their desktop. This is the relevant model:
class ComputerOrder(forms.Form):
name = forms.CharField(max_length=50)
office_address = forms.Charfield(max_length=75)
pc_type = forms.ChoiceField(widget=RadioSelect(), choices=[(1, 'Mac'), (2, 'PC')])
On the template, how do I render just the Mac choice button? If I do this, it renders all the choices:
{{ form.pc_type }}
Somewhat naively I tried this, but it produced no output:
{{ form.pc_type.0 }}
(I found a few similar questions here on SO:
In a Django form, how do I render a radio button so that the choices are separated on the page?
Django Forms: How to iterate over a Choices of a field in Django form
But I didn't feel like they had good answers. Is there a way to resurrect old questions?)
Django 1.4+ allows you to iterate over the choices in a RadioSelect, along with the lines of
{% for choice in form.pc_type %}
{{ choice.choice_label }}
<span class="radio">{{ choice.tag }}</span>
{% endfor %}
I'm not sure if this change allows you to use the syntax you describe ({{ form.pc_type.0 }}) — if not, you could work around this limitation with the for loop above and a tag like {% if forloop.counter0 == 0 %}.
If you're tied to Django < 1.4, you can either override the render() method as suggested or go with the slightly-more-verbose-but-less-complicated option of building up the form field yourself in the template:
{% for choice in form.pc_type.field.choices %}
<input name='{{ form.pc_type.name }}'
id='{{ form.pc_type.auto_id }}_{{ forloop.counter0 }}' type='radio' value='{{ choice.0 }}'
{% if not form.is_bound %}{% ifequal form.pc_type.field.initial choice.0 %} checked='checked' {% endifequal %}
{% else %}{% ifequal form.pc_type.data choice.0 %} checked='checked' {% endifequal %}{% endif %}/>
<label for='{{ form.pc_type.auto_id }}_{{ forloop.counter0 }}'>{{ choice.1 }}</label>
{% endfor %}
(choice.0 and choice.1 are the first and second items in your choices two-tuple)
The rendering of the individual radio inputs is handled by the RadioSelect widget's render method. If you want a different rendering, subclass RadioSelect, change the render method accordingly, and then use your subclass as the field's widget.
I think the simply looking at what's available inside the for loop of a choice field will tell one what they need to know. For example, I needed the value to set a class surrounding the span of the option (for colors and such):
<div>
{% for radio_input in form.role %}
{# Skip the empty value #}
{% if radio_input.choice_value %}
<span class="user-level {{ radio_input.choice_value }}">{{ radio_input }}</span>
{% endif %}
{% endfor %}
</div>
There are several attributes as you can see that keep you from having to use the ordinal.
In Django 2.0+ you can subclass forms.RadioSelect and "simply" specify a template for rendering the radio fields:
class SlimRadioSelect(forms.RadioSelect):
template_name = 'includes/slim_radio.html'
where slim_radio.html contains a revised version of the combined template_name and option_template_name used by the default RadioSelect widget.
Note, the default RadioSelect widget template is low-level rendering and consists of heavily layered templates: include, conditional and loop logic tags abound.
You'll know you've arrived when you're digging around in packages/django/forms/templates/django/forms/widgets/input.html to get what you need.
One other oddity for overriding the default widget's template is that you must invoke the TemplatesSetting renderer or your subclass won't be able to find slim_radio.html in your project's normally accessible template paths.
To override RadioSelect's local-only template path lookup:
Add 'django.forms' to your INSTALLED_APPS;
Add FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' to your settings.py.
This all seems harder than it should be, but that's frameworks. Good luck.
class BaseForm(forms.Form):
def as_custom_table(self):
"Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
return self._html_output(
normal_row = u'<tr%(html_class_attr)s><td class="label_col">%(label)s</td><td class="field_col">%(field)s%(help_text)s</td></tr>',
error_row = u'<tr><td colspan="2" class="error">%s</td></tr>',
row_ender = u'</td></tr>',
help_text_html = u'<br />%s',
errors_on_separate_row = True)
I'm trying to see if I can get django to do the heavy lifting and render a form in the way I want it to render.
The problem here is, there might be one or two fields that need to render slightly differently. Such as a "please confirm you agree to our terms and conditions" check box, which would need to span two columns.
Also some other things, such as error placement, might need changing.
I could override the _html_output method to change error placement, but what about getting an individual field to use a different render method?
I think ultimately I need to revert to manually building the form html in the template, but I'm just wondering how much of it Django could do for me with some minor modifications.
The suggested method will be to use a template like this:
<form action="/contact/" method="post">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
You can conditionally override specific fields using {{ if field.my_property }}.