Jinja dictionary value not showing - python

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

Related

HTML table from python dictionary

I am trying to modify part of code in a flask application. What the flask app does so far:
It has around 20 links, when someone clicks on the link it returns .json objects (formed by python dictionaries via jsonify).
What I am trying to do:
Return the same results in a table format that can be potentially extracted to .csv
I created the following function:
def tab_out(output = {}):
return render_template('output_tab.html',output=output)
that sends the dictionary out to an html page, that contains this:
{% block content %}
<body>
<pre>
<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
</tr>
{% for key_1, value in output.items() %}
{% for key in value.keys() %}
<tr>
<td>
{{ key_1 | safe }}
</td>
<td>
{{ key | safe }}
</td>
<td>
{{ value[key]["Header_3"] }}
</td>
<td>
{{ value[key]["Header_4"] }}
</td>
<td>
{{ value[key]["Header_5"] }}
</td>
<td>
{{ value[key]["Header_6"] }}
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
</pre>
</body>
{% endblock %}
What's the issue:
I need to make it dynamic.
Each page has different headers.
In each page the resulted .json comes from a dictionary that has sub-dictionaries and the number of keys in each dictionary can be different. So I can't specify the headers before hand. I want them dynamically created. Maybe flatten out the dictionary (up to a level 2 let's say) if there's 3 sub-dictionaries and get the results as headers and the rest as values.
I've read a couple similar questions in sa, but none of them really helped me. Any ideas?
The jinja code below will generate HTML table from any FLAT dict.
The headers are dynamic. entry_list is a list of dicts. Your code should create a flat dict.
<table style="width:100%">
<!-- table header -->
{% if entry_list %}
<tr>
{% for key in entry_list [0] %}
<th> {{ key }} </th>
{% endfor %}
</tr>
{% endif %}
<!-- table rows -->
{% for dict_item in entry_list %}
<tr>
{% for value in dict_item.values() %}
<td> {{ value }} </td>
{% endfor %}
</tr>
{% endfor %}
</table>

Accessing Value in Dictionary thru Jinja

In the Python file that controls the Jinja template I create a dictionary:
disp_list = {}
for comp in requested_workspace.components:
if comp.show_on_report_list:
disp_list[comp.label] = {}
disp_list[comp.label]['descrip'] = comp.description
In the Jinja template I want to display values from the dictionary:
<table class="table table-hover">
<tbody>
{% for listing in disp_list %}
<tr>
<td>
{{ listing }}
</td>
<td>
{{ listing['descrip'] }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ listing }} displays but {{ listing['descrip'] }} won't display. Am I accessing the 2nd value incorrectly?
The Python file controlling the Jinja template was fine. I didn't change it. The Jinja template (HTML file) was where the change was needed.
{% for item_name, values in disp_list.items() %}
<tr>
<td>
{{ item_name }}
</td>
<td>
{{ values['descrip'] }}
</td>
</tr>
{% endfor %}
Using .items() allows me to use tuple explosion and get 2 values out of the dictionary.

Django Object Filter

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

Reading data of multiple level of multiple checkboxes in Django

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.

How to insert conditional fields with WTForms?

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!

Categories

Resources