In a website I'm building with Flask I'm using WTForms for form validation. I currently have a field which is dependent on another field: if a user inserts a specific year (2012) a couple radio buttons are inserted using Javascript. I made the RadioField optional, which works fine, but if I actually do submit the form with the radiobuttons the value of it remains None.
To talk some code; the two relevant form fields are defined as follows:
construction_year = IntegerField('construction_year')
transfer_tax_rate = SelectField('transfer_tax_rate', validators=[Optional()], choices=[('ZERO', '0%'), ('SIX', '6%')])
the code I first used in the template to display the construction_year and transfer_tax_rate is as follows:
{{ form.construction_year(size=10) }}
{{ form.transfer_tax_rate() }}
This works fine; I can print out the values on the back end like so:
if form.validate_on_submit():
print form.construction_year.data # prints out '2012'
print form.transfer_tax_rate.data # prints out ZERO or SIX depending on my choice
I then removed {{ form.transfer_tax_rate() }} and wrote some Javascript which inserts the some html if the construction_year is 2012:
function displayTransferTaxRate(){
var year = $("#construction_year").val();
var propertyType = $("#property_type").val();
if (year.length == 4 && year == 2012) {
var transferTaxRateHtml = 'Applicable tax rate <select id="transfer_tax_rate" name="transfer_tax_rate"><option value="ZERO">0%</option><option value="SIX">6%</option></select>';
$('#transfer-tax-rate-div').html(transferTaxRateHtml);
} else {
$('#transfer-tax-rate-div').html('');
}
}
$("#construction_year").on('keyup paste', displayTransferTaxRate);
for easy reading; the html it inserts is as follows:
<select id="transfer_tax_rate" name="transfer_tax_rate">
<option value="ZERO">0%</option>
<option value="SIX">6%</option>
</select>
The html gets inserted fine, and I can select either of the options. But when I submit the form and try to get the value of the transfer_tax_rate as follows, it always prints out None:
if form.validate_on_submit():
print form.construction_year.data # prints out '2012'
print form.transfer_tax_rate.data # prints out None
Does anybody have any idea what I'm doing wrong here? All tips are welcome!
[EDIT]
Following the tip from user3147268 below I aslo tried getting it from the standard flask request.form, but that doesn't contain an entry for 'transfer_tax_rate' either.
Okay, after about 5 hours of banging my head against the wall, I'll answer my own question, because you guys could not have known this.
It turns out that it was related to a table in which this form was embedded. I left that information out, because I didn't expect that to be relevent.
So this works fine:
<table>
<form action="" method="post" id="prop-form">
{{ form.hidden_tag() }}
<tr>
<td>Construction year: </td>
<td>
{{ form.construction_year(size=10) }}
</td>
</tr>
<tr>
<td>Transfer tax rate: </td>
<td>
{{ form.transfer_tax_rate()
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Save property"></td>
</tr>
</form>
</table>
But when I add the exact same html in this div, it doesn't work anymore:
<table>
<form action="" method="post" id="prop-form">
{{ form.hidden_tag() }}
<tr>
<td>Construction year: </td>
<td>
{{ form.construction_year(size=10) }}
<div id="transfer-tax-rate-div"></div>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Save property"></td>
</tr>
</form>
</table>
whereas, without the table around it, it does work:
<form action="" method="post" id="prop-form">
{{ form.hidden_tag() }}
Construction year: {{ form.construction_year(size=10) }} <br />
<div id="transfer-tax-rate-div"></div>
<input type="submit" value="Save property">
</form>
The solution turned out to lie in the placement of the <form> tags, because if I move them out of the table like this last piece of code, it all works fine:
<form action="" method="post" id="prop-form">
{{ form.hidden_tag() }}
<table>
<tr>
<td>Construction year: </td>
<td>
{{ form.construction_year(size=10) }}
<div id="transfer-tax-rate-div"></div>
</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Save property"></td>
</tr>
</table>
</form>
Excuse me for bothering all you guys and girls time whilst not providing all the relevant information. Thank you for giving me the energy to keep on looking though!
Related
I am using django formset to submit a dynamically generated form (based on a file uploaded by the user). The template renders this form manually (I prefer this because it's easier for me to work on style+HTML together in template). On submitting the form, I get an error that id is a required field. My form template looks like this:
<form method="post" id="add3">
{{ formset.management_form }}
{% csrf_token %}
<table id="forms">
<tbody>
{% for lst in result %}
<input type="hidden" name="form-{{ forloop.counter0 }}-id" value="{{ forloop.counter }}" id="id_form-{{ forloop.counter0 }}-id">
<tr>
<td>
<input type="hidden" name="form-{{ forloop.counter0 }}-expense" id="id_form-{{ forloop.counter0 }}-expense" value="{{lst.0}}"/>
</td>
<td>
<input type="hidden" name="form-{{ forloop.counter0 }}-amount" id="id_form-{{ forloop.counter0 }}-amount" value="{{lst.1}}"/>
</td>
{% endfor %}
</tbody>
</table>
</form>
This is a short version. I have 6 fields in each row. I am able to get all 6 fields but it complains about the id. I have added the hidden id input type in each row but that doesn't work. How can I fix this?
I have a simple filter where a user enters a string, term, which is compared against the column companyId in my local database. If there is a match, the appropriate record/s are then rendered in a table within my template. However, no data is being rendered in the template, only rows of empty fields matching the number of records for a particular query. I have similar logic used for displaying these records unfiltered which works fine.
Edit:
When I removed the key value and tried to render only the object such as {{ object }}, the following is displayed: (Opportunity: Opportunity object (8)
views.py
def opportunity_dashboard(request):
try:
term = request.GET.get('search_query')
if term:
filtered_objects = Opportunity.objects.filter(companyId__icontains=term)
filtered_local_zip = zip(filtered_objects)
context = {
'term': term,
'filtered_local_zip': filtered_local_zip,
'filtered_connectwise_zip': filtered_connectwise_zip
}
return render(request, 'website/opportunity_dashboard.html', context)
template.html
{% if term %}
{% for object in filtered_local_zip %}
<tr>
<th style="text-align: center;">
✎
</th>
<td>
<div class="select">
<select disabled id="bw_status" name="status">
<option value="{{ object.status }}">{{ object.status }}</option>
</select>
</div>
</td>
<td>
<a{{ object.opportunityName }}</a>
</td>
<td>{{ object.companyId }}</td>
<td>
<div class="select">
<select id="bw_account_manager" name="account_manager">
<option value="{{ object.accountManager }}">{{ object.accountManager }}</option>
</select>
</div>
</td>
You don't need zip() nor list() to iterate over a queryset in a Django template.
Simply pass it to the context.
filtered_local_zip = filtered_objects
and in the template iterate over it like you're already doing:
{% for object in filtered_local_zip %}
If you need to iterate over zip(), read this: https://stackoverflow.com/a/4238261/1307020
Which suggests either this
{% for object0, object1 in filtered_local_zip %}
or this
{{ object.0.property }}
Demonstration: https://repl.it/repls/UntidyLimpingCollaborativesoftware
I'm working on a Flask App where I create a form with RadioFields as choices, and I also pass a param2 dict through to the jinja client-side.
I successfully render the individual Radiofields as subfields but I can not seem to render the text for the dict value that accompanies the key.
The label of the radiofield is also the key of the dict in param2, and I'm trying to get it's value printed next to the subfield.label text.
param2 looks like this:
param2{'Text Label1': 'completed', 'Text Label2': 'busy'}
When I print {{ param2 }} on the page, I get the dict as it should be.
{'Text Label1': 'completed', 'Text Label2': 'busy'}
Here is how I print the subfield and call the dict.
<form method="post">
<table>
{% for subfield in form.display %}
<tr>
<td> {{ form.csrf_token }} </td>
<td> {{ subfield }} {{ subfield.label }} </td>
<td> {{ param2[subfield.label] }} </td>
</tr>
{% endfor %}
</table>
<input type="submit" value="Generate">
<button type="reset" value="Reset">Reset</button>
</form>
When the code renders, the param2's <td> </td> is empty:
<tr>
<td> <input id="display-0" name="display" type="radio" value="5"> <label for="display-0">Text Label1</label> </td>
<td> </td>
</tr>
Output I'm trying to get
<> Text Label1 completed
<> Text Label2 busy
I found the problem.
As #sergey-shubin said, the subfield.label property of the form is an HTML construct,
meaning:
if you call {% subfield.label %}
then you will get <label for="display-0">Text Label1</label>. <-- HTML Construct
Solution:
You can extract the label itself from the construct by calling the text method subfield.label.text which yields Text Label1 from the HTML construct.
Answer found here
I have a page that is something like below:
<table>
<tr>
<th>ID</th>
<th>Edit</th>
</tr>
<form action="/edit_submit/" method="POST">
{% for item in result %}
<tr>
<td>{{ item.id }}</td>
<td>
<input type="checkbox" name="options" id={{ item.id }} value="1">Apple
<input type="checkbox" name="options" id={{ item.id }} value="2">Water
<input type="checkbox" name="options" id={{ item.id }} value="3">Cake
{% csrf_token %}
</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="Submit">
</form>
I need a way to read all the checkboxes value with name options on the page during submit, without knowing the item.id values. Hence I need an output which gives me tuples as item.id,value,checked.
I know that id is not unique here, however is there a better solution for grouping checkboxes? I can put item.id as name in html, but remember I do not know the item.id which appeared on the page.
I have a list of members, from a for loop in jinja2 with select and option
I would like to be able to select one of the members from the for loop,
and add that member to another list of entries to an event, with the extra options available to the user. (getting the member is easy, from the value of the button, getting the options is the problem)
For example:
Jinja2 Template:
<form method="post" action="add_member_to_list">
<table>
{% for member in members %}
<tr>
<th>{{ member.name }}</th>
<td><input type="checkbox" name="in_out"></td>
<td><select name="day">
<option>Monday</option>
<option>Wednesday</option>
</select>
</td>
<td><button type="submit" name="id" value="{{ member.id }}">Add</button></td>
</tr>
{% endfor %}
</table>
</form>
in Google App Engine - Python
class AddUser(BaseHandler):
def post(self):
in_out = self.request.get("in_out")
id = self.request.get("id")
day = self.request.get("day")
In this scenario, self.response.get("day") only ever returns the option selected for the first iteration of the for loop.
The checkbox; self.request.get("in_out"), returns on or off as expected.
So submitting the nth iteration of the for loop:
"Monday" is always returned from select/option.
How can I get the select/option corresponding to the nth iteration of the for loop?
Thanks!
The simplest solution will be to move the form tag into your for loop
<table>
{% for member in members %}
<form method="post" action="add_member_to_list">
<tr>
<th>{{ member.name }}</th>
<td><input type="checkbox" name="in_out"></td>
<td><select name="day">
<option>Monday</option>
<option>Wednesday</option>
</select>
</td>
<td><button type="submit" name="id" value="{{ member.id }}">Add</button></td>
</tr>
</form>
{% endfor %}
</table>
So your resulting form has multiple fields with the same name, right?
Like for the first member, there is a and for the second member, there is also a ?
If so, forms don't support that. You have to have a unique name for each field. You'll have to throw in a memberID on each iteration of the loop, or come up with a better design. Something like <select name="day{{member.id}}"> would be a hacky fix.
Another way is you just leave the in_out and day OUT of the for loop, keep it outside.
I hope that helps.
I found a quite simple solution for this:
instead of
day = self.request.get("day")
I used
day = self.request.get_all("day")
Which returns a list of all the options from the select, including the option the user choose for the member.
Then, for the Add Button, instead of
<td><button type="submit" name="id" value="{{ member.id }}">Add</button></td>
I assigned the name "loop" and a value of {{ loop.index0}}
so,
self.request.get("loop")
returns the position of the member selected, corresponding the position on the day list of the target. voila.
The member I get from a hidden td instead of from the submit button.
The final code:
<form method="post" action="add_member_to_list">
<table>
{% for member in members %}
<tr>
<th>{{ member.name }}</th>
<td><input type="checkbox" name="in_out"></td>
<td>
<select name="day">
<option>Monday</option>
<option>Wednesday</option>
</select>
</td>
<td class="hidden"><input name="id" value="{{ member.id }}"></td>
<td><button type="submit" name="loop" value="{{ loop.index0 }}">Add</button></td>
</tr>
{% endfor %}
</table>
</form>
class AddUser(BaseHandler):
def post(self):
day = self.request.get_all("day")
id = self.request.get_all("id")
loop = self.request.get("loop")
target_day = day[int(loop)]
target_id = id[int(loop)]
Niiice.