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)
Related
I'd like to add a single form input field to a DetailView that will append tags to my model. I'm not sure if I need a separate view for that, or I can simply add a form. Using django-bootstrap3, I have the following:
<div class="row">
<form action="add-tag" method="post"
enctype=multipart/form-data>
{% csrf_token %}
{{ form.media }}
{% bootstrap_field form.tags show_label=False %}
<input type="submit" value="{% trans "submit" %}"/>
</form>
</div>
forms.py:
class MyModelAddTagsForm(forms.ModelForm):
class Meta:
model = models.MyModel
fields = ('tags',)
I get the error:
BootstrapError at /someurl/1/view
Parameter "field" should contain a valid Django BoundField.
I'm not sure what else I exactly need. A view and url or modifying my DetailView? Or using an UpdateView instead?
I am using django-webtest to create automated functional tests for my application.
As I have multiple forms on a single web page, I'm currently using a hard-coded index to select the form of interest. For instance:
# Forms on this page are: forms[0] = Establishment form,
# forms[1]= School Form
school_form = school_page.forms[1]
school_form['phone'] = self.school_phone_number
school_form.submit(value='Submit')
I would like to use the form id instead of a hard-coded index to select the form of interest, so that the code is maintainable. But when I print school_form.id in my code, the value is None.
Template is:
<form action="" method="post" >
{% csrf_token %}
<p>
{{ establishment_form|crispy }}
<br><br>
{{ school_form|crispy }}
</p>
<button type="submit" class="btn btn-lg btn-primary">Submit</button>
I couldn't locate in the Django documentation how to assign the form id (not the form field id) to a ModelForm. Could someone help me with this?
I'm using Django 1.7, django-webtest 1.7.8, WebTest 2.0.18 and django-crispy-forms 1.4.0.
Django forms aren't responsible for outputting the form element itself. So there is nothing to be done at the form declaration level.
You can always pass an attribute from the view and use it in your template:
<form id="{{ form_id_from_view }}" action="." method="POST">
You can directly assign the id to the form element in your template.
<form id="my_id" name="some_name" action="/my/url/" method="POST">
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.
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', [...])
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 }}.