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', [...])
Related
I have generated a simple contact form with four fields using Wagtail Form Builder. The challenge I'm having, is that I'm unable to reference the form fields with css classes individually, since I'm not sure where I should get the field id and label name from.
Here is the code that renders the form:
<h1>{{ page.title }}</h1>
{{ page.intro|richtext }}
<form action="{% pageurl page %}" method="POST" class="sky-form contact-style">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
If referencing the fields individually is not possible, what will be the other method(s) to achieve the same result?
Wagtail formbuilder creates a dynamic form - the id (name) of each field is created by the following code: str(slugify(text_type(unidecode(self.label))))
(from https://github.com/torchbox/wagtail/blob/master/wagtail/wagtailforms/models.py#L90)
So the field label is converted to ascii characters and then to a slug. For example, if you have a field name First Name it will be converted to 'first-name'.
An easy way to find out what is the actual id of the form fields that wagtail formbuilder creates is to actually output the fields in a template by enumerating them:
{% for field in form %}
{{ field }}
{% endfor %}
and then inspect the produced html code to see their actual ids (you'll see <input class="textinput textInput" id="id_first-name" maxlength="255" name="first-name" type="text"> so you'll know that the id of the field is first-name)
I want the user to be able to select a time period from the drop down then select the number of appointments needed with that time span and have it added to a list. I have been able to accomplish this with simply javascript and Html, but am at a loss as how to get all the values from the table after the user clicks 'submit'.
If I used Django's form API then the fields in the table would display as editable textboxes. Is there a way to make a form with labels/non-editable text instead of fields? That way I can edit the labels with javascript and the values will get passed to the view on Post.
I am new to Django so any suggestions are welcome.
Example
Forms.py Example - Not what I want:
class AppointmentForm(forms.Form):
TimePeriod = forms.IntegerField(label='Time Period')
Amount = forms.IntegerField(label='Amount')
AppointmentFormSet = formset_factory(AppointmentForm)
When I solved much more complex generated form, I just created view, which collected some data, set context and rendered template.
That template was "old style" form, with all the tags written by hands/loops and so, like
{% for p in pairs %}
<option name="name_{{p.id}}" value="{{p.val}}">
{% endfor %}
and
{% for v in vars %}
<input type="text" name="{{v.name}}" value="{{v.val}}">
{% endfor %}
and the form ended in view, where I was looping over request.POST and parsing it manually (mainly)
Not very Django way, but you can do ANYTHING with this approach (and shoot yourself to any leg any time you want too)
Presumably by "labels" you just mean non-editable text, so it could be a <div> or a <p> etc - in this case you will need to have a hidden input which mirrors the content of the label, i.e.
<div class="label">Text here</div>
<input type="hidden" name="form-field-name" value="Text here">
To achieve this in your form, use a forms.HiddenInput widget:
class AppointmentForm(forms.Form):
time_period = forms.IntegerField(widget=forms.HiddenInput)
Obviously the django form isn't going to render the way you need it to, so you'll need to render it using custom html, which will probably look something like this:
{% for field in form %}
<div class="label">{{ field.data }}</div>
{{ field }}
{% endfor %}
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}}?
I have a formset which i initialize it in view. one of the form's fields is FileField. and I have to show user the name of his/her previous file name. Because i can't initialize FileField, i want to send file names in list. (I mean for example when you have a Charfield, you can initialize it in views and when you render to template, you will see an input filled with that data, but when you have file upload field you can't filled it in views and sends to template). i don't know how i can loop over forms in formset and list at the same time. And the other thing is when i initialize forms in formset and render to template (I mean for example write data['form-0-Team']='team1' but i can't write data['form-0-Team']='a.png' , so when i render to template, i see field named 'Team' is filled (value=team1) and field named 'File' is not filled and the error 'thid field is required' id shown. ) although it's the first time i'm visiting this page and my method isn't POST. (USUALLY form errors are shown when user clicks on submit and in views it checks if request.method == 'POST', then checks if form.is_valid, it return to template and shows errors, but in mine, it shows errors at the first time euser is visiting the page and before he/she posts data).
I wish i could say my problem. can you please guide me solve this? really thanks.
def myFunc(request):
flagFormSet = formset_factory(FlagFileBaseForm)
if request.method == 'POST':
formset = flagFormSet(request.POST, request.FILES)
if formset.is_valid():
# do s.th
else:
data = {
'form-TOTAL_FORMS': 5,
'form-INITIAL_FORMS': u'0',
'form-MAX_NUM_FORMS': u'',
# add initial form data to it
}
list=['a.png', 'b.png', 'c.png', 'd.png' , 'f.png']
formset = flagFormSet(data)
return render_to_response('myPage.html', RequestContext(request, { 'formset': formset, 'list':list}))
and my template:
<form method="post" action="" enctype="multipart/form-data">
{{ formset.management_form }}
{% for form in formset.forms %}
<div class="form">
<div class="form-row Team">
<div>
<label class="required" for="id_Team">Team:</label>
{{ form.Team }}
{{ form.Team.errors }}
</div>
</div>
<div class="form-row File">
<div>
<label class="required" for="id_File">File:</label>
{{ form.File }}
{{ form.File.errors }}
</div>
#here i want show the name of previous file
</div>
</div>
{% endfor %}
</form>
EDIT:
current result (while request is not post, it shows error)
desired result (form without error with file names)
In Django Templates, if you are trying to render a form that has a FileField. You must pass replace
<form method="post" action="">
with
<form method="POST" enctype="multipart/form-data">
https://docs.djangoproject.com/en/dev/ref/forms/api/#binding-uploaded-files-to-a-form
I'm afraid I don't really understand your question, so apologies if this doesn't help..
If your list is arbitary (as it looks from your question), then you could use django's built in forloop counter to construct your file names -
{% for form in formset %}
{{ form }}
<input type="text" name="file_name" value="{% forloop.counter %}.png">
{% endfor %}
Alternatively have a look at python's zip function. You could use it to build an object that includes both the names and the forms and pass that to your template.
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 }}.