Flask - Query CSV and Pass Results to render_template() - flask

I have created two web pages - index and reports.
The index page contains an input box where the user can enter a Zip Code. When the submit button is pressed, the code reads in and queries a CSV file based on the Zip Code. The results are then passed to render_template.
When I run my code, all that displays on the reports page is the header row of the CSV file.
I am not sure what I am doing incorrectly.
Below is a snippet of my app.py file
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/reports', methods=['POST'])
def reports():
zip_code = request.form.get('zip_code')
df = pd.read_csv('real-estate.csv')
myData = df[df['zip'] == zip_code]
return render_template('reports.html', zip_code=zip_code, myData=myData)
Below is the contents of my reports file.
{% extends 'base.html' %}
{% block content %}
<div class='container'>
<h2>Real Estate Transactions</h2>
<ul>
{% for rec in myData %}
<li>{{ rec }}</li>
{% endfor %}
</ul>
</div>
{% endblock %}

Try using iterrows() to iterate over the rows of the dataframe.
<ul>
{% for key,value in myData.iterrows() -%}
<li id="row-{{key}}">{{value}}</li>
{% endfor -%}
</ul>
An example of a table would then look something like this.
<table>
<thead>
<tr>
{% for column in myData.columns -%}
<th>{{column}}</th>
{% endfor -%}
</tr>
</thead>
<tbody>
{% for key,value in myData.iterrows() -%}
<tr id="row-{{key}}">
{% for v in value.values -%}
<td>{{v}}</td>
{% endfor -%}
</tr>
{% endfor -%}
</tbody>
</table>

Related

Django 2.2 How to disable checkboxes in list view

Django 2.2
I have a list view controlled by admin.py class. No custom template, all default. I can control what fields from the table should be shown in the view with this:
fields = ('myfield1','myfield2', ...).
Each row in the list table has a checkbox in the first column, the source looks like this:
<td class="action-checkbox">
<input type="checkbox" name="_selected_action" value="123" class="action-select">
</td>
My questions are:
How to disable those checkboxes (preferably, from Django code, without introducing a custom template) ?
Can it be done for SOME of the checkboxes (let's say I have a list of pk ids for the rows I don't want to see checkboxes.)
You can delete Items with those CheckBoxes, but if you want to customize your own admin page to override it
You can use this doc https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#admin-overriding-templates
This question is 2 years old now, but for the case someone still needs it, the following code works to overwrite the change-list_results.html:
{% load i18n static %}
{% if result_hidden_fields %}
<div class="hiddenfields">{# DIV for HTML validation #}
{% for item in result_hidden_fields %}{{ item }}{% endfor %}
</div>
{% endif %}
{% if results %}
<div class="results">
<table id="result_list">
<thead>
<tr>
{% for header in result_headers %}
{% if "checkbox" in header.text %}
{% else %}
<th scope="col" {{ header.class_attrib }}>
{% if header.sortable %}
{% if header.sort_priority > 0 %}
<div class="sortoptions">
<a class="sortremove" href="{{ header.url_remove }}" title="{% translate "Remove from sorting" %}"></a>
{% if num_sorted_fields > 1 %}<span class="sortpriority" title="{% blocktranslate with priority_number=header.sort_priority %}Sorting priority: {{ priority_number }}{% endblocktranslate %}">{{ header.sort_priority }}</span>{% endif %}
</div>
{% endif %}
{% endif %}
<div class="text">{% if header.sortable %}{{ header.text|capfirst }}{% else %}<span>{{ header.text|capfirst }}</span>{% endif %}</div>
<div class="clear"></div>
{% endif %}
</th>{% endfor %}
</tr>
</thead>
<tbody>
{% for result in results %}
{% if result.form and result.form.non_field_errors %}
<tr><td colspan="{{ result|length }}">{{ result.form.non_field_errors }}</td></tr>
{% endif %}
<tr>
{% for item in result %}
{% if "_selected_action" in item %}
{% else %}
{{ item }}
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
It stops stops the output of the for loops if theres a checkbox in there. --> It just removes the checkboxes.

Django template integer value iteration

I have the following model
class Table(models.Model):
# Some not important attrs
rows = IntegerField(etc)
cols = IntegerField(etc)
Then I have my view where I'm rendering objects of this model. And I need to build some HTML tables based on the quantity of each objects' rows and cols.
View:
get_tables(request):
tables = Table.objects.all()
return render(request, 'tables.html', {'tables': tables})
I'm trying to do something like:
{% for table in tables %}
<table>
<thead>
<tr>
{% for col in table.cols %}
<th>column label here</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in table.rows %}
<tr>my row</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
I know it is possible to loop for key in dict. But the values cols and rows are integers. How can I achieve this on a Django template?
Try
{% for table in tables %}
<table>
<thead>
<tr>
{% with ''|center:table.cols as range %}
{% for _ in range %}
<th>column label here</th>
{% endfor %}
{% endwith %}
</tr>
</thead>
<tbody>
{% with ''|center:table.rows as range %}
{% for _ in range %}
<tr>my row</tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
{% endfor %}
# You can take use of filter tags in django template
# For Example
Step 1:- Create 'templatetags' package in your app folder.
Step 2:- Create filter.py in 'templatetags' package
Step 3:-
from django import template
register = template.Library()
def table_rows(value):
value_list = [value]
html_row = ''
for val in value_list:
html_row += '<tr></tr>'
return html_row
def table_cols(value):
value_list = [value]
html_cols = ''
for val in value_list:
html_cols += '<td>Hello</td>'
return html_cols
register.filter('table_rows', table_rows)
register.filter('table_cols', table_cols)
Step 4:-
# Your template can be:-
{% load filter %}
{% for table in tables %}
<table border="1">
{% autoescape off %}
{{table.rows|table_rows}}
{{table.cols|table_cols}}
{% endautoescape %}
</table>
{% endfor %}
# You can make changes according to your requirement

get a List of List object and how to handle it in html with django

index.html
{% block content %}
{{playerList}}
{% for player in playerList %}
{{player.value.indexOf(0)}}
{% empty %}
<tr>
<td class="bg-light text-center font-italic" colspan="3">You haven't registered any players yet.</td>
</tr>
{% endfor %}
{% endblock %}
playerList is a list of lists, which is returned from views.py file.
i.e playerList=[["chamo",'1'],["gir",'2'],["frt",'2']]
if I want to get the "chamo" from playerList, how should I write it in html file?
You can just do {{ player.0 }}.

What's the correct way to print a matrix with labels in a Django template?

I want to do something very simple in Django: Print a matrix as an HTML table, and add labels for the rows and columns. These are the variables in my view:
matrix = np.array([
[101, 102, 103],
[201, 202, 203],
])
colnames = ['Foo', 'Bar', 'Barf']
rownames = ['Spam', 'Eggs']
I want a to get a table that looks like this:
Foo Bar Barf
Spam 101 102 103
Eggs 201 202 203
My template code looks like this:
<table>
<tr>
<th></th>
{% for colname in colnames %}
<th>{{ colname }}</th>
{% endfor %}
</tr>
{% for rowname in rownames %}{% with forloop.counter0 as rowindex %}
<tr>
<th>{{ rowname }}</th>
{% for colname in colnames %}{% with forloop.counter0 as colindex %}
<td>TABLECELL</td>
{% endwith %}{% endfor %}
</tr>
{% endwith %}{% endfor %}
</table>
Output for different values of TABLECELL:
{{ rowindex }}, {{ colindex }} --> table with the indices :)
{{ matrix.0.0 }} --> table full of 101s :)
{{ matrix.rowindex.colindex }} --> table with empty cells :(
As the first two things work, it doesn't seem crazy to assume that the last one would give the intended result. My only explanation is that rowindex and colindex might be strings — and of course int() is among the many things that are forbidden in Django templates.
Does anyone know how I can make this work? Or ideally:
Does anyone know how this is intended to be done in Django?
EDIT 1:
It seems I have to pass the enumerated lists to the template. I provide them as enum_colnames and enum_rownames, but now I can't even execute the nested for loop:
<table>
<tr>
<th></th>
{% for unused_colindex, colname in enum_colnames %}
<th>{{ colname }}</th>
{% endfor %}
</tr>
{% for rowindex, rowname in enum_rownames %}
<tr>
<th>{{ rowname }}</th>
{% for doesnt_work_anyway in enum_colnames %}
<td>You don't see me.</td>
{% endfor %}
</tr>
{% endfor %}
</table>
This gives a table with all the <th>s filled with the correct labels, but no <td>s at all.
EDIT 2:
I found an insanely ugly "solution", which I publish here as an example of something that "works", but is clearly not an answer to my question — how this should be done in Django. Here it comes:
derp = ['', 'Foo', 'Bar', 'Barf', 'Spam', 101, 102, 103, 'Eggs', 201, 202, 203]
iderp = enumerate(derp)
<table>
{% for i, d in iderp %}
{% if i < 4 %} <!-- if top row: th -->
{% cycle '<tr><th>' '<th>' '<th>' '<th>' %}
{% else %} <!-- else: td -->
{% cycle '<tr><th>' '<td>' '<td>' '<td>' %}
{% endif %}
{{ d }}
{% if i < 4 %} <!-- if top row: th -->
{% cycle '</th>' '</th>' '</th>' '</th></tr>' %}
{% else %} <!-- else: td -->
{% cycle '</th>' '</th>' '</td>' '</td></tr>' %}
{% endif %}
{% endfor %}
</table>
Note how it can only be used for tables of this particular width. So in this form it is not even a real solution for the initial problem.
Thanks to Paulo Almeida for providing the two essential hints in his answer:
The table — including labels — should be built in the view.
forloop.first can be used to put the labels in <th>s.
table = [
['', 'Foo', 'Bar', 'Barf'],
['Spam', 101, 102, 103],
['Eggs', 201, 202, 203],
]
<table>
{% for row in table %}
<tr>
{% for cell in row %}
{% if forloop.first or forloop.parentloop.first %} <th> {% else %} <td> {% endif %}
{{ cell }}
{% if forloop.first or forloop.parentloop.first %} </th> {% else %} </td> {% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
I guess the answer to my implicit question — how the values of multidimensional arrays can be accessed from the template — is that this is not possible.
Your problem seems to be a good use case for a feature request suggesting the use of iterables in the cycle tag. Then you could just {% cycle rownames %} in the first <td>.
Unfortunately, that's not possible, as far as I can see. I would take that logic away from the template and into the view (or, more likely, an utility function or model method, depending on the specifics), building a list that is easy to process in the template:
table = [
['Spam', 101, 102, 103],
['Eggs', 201, 202, 203],
]
The function to build the table might look like this:
def build_table(rownames, matrix):
table = []
for rowname, values in zip(rownames, matrix):
row = [rowname]
row.extend(values.tolist())
table.append(row)
return table

How to access values for a key in a Django template?

Newbie Question:
I have a dictionary rendering with extra_Context from a method defined in views.py
My views:
extra_context = {
'comment': comment
}
return direct_to_template(request, 'events/comment_detail.html', extra_context)
If i print the comment the it print like this:
[{'comment': u'first', 'user': 2}, {'comment': u'second', 'user': 2}]
I want to pass this dictionary to my template. I tried with this following code:
<tbody>
{% for obj in comment %}
{% for key,val in obj.items %}
<tr class="{% cycle 'odd' 'even' %}">
<td> {{val}}</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
It prints :
first
2
second
2
I want in this way:
first 2
second 2
..and so on
What should i add it to get like above ?
Updated!
def comment_detail(request, object_id):
comment_obj = EventComment.objects.filter(event = object_id)
comment = comment_obj.values('comment','user')
extra_context = {
'comment': comment
}
return direct_to_template(request, 'events/comment_detail.html', extra_context)
comment_detail.html
<form action="" method="POST">
<table>
<thead>
<tr><th>{% trans "Comments" %}</th><th>{% trans "Timestamp "%}<th>{% trans "User" %}</th></tr>
</thead>
<tbody>
{% if comments %}
{% for com in comment %}
<td> {{com.comment}}</enter code heretd>
<td> {{com.user}}</td>
{% endfor %}
{% else %}
<td> No comments </td>
{% endif %}
</tr>
</tbody>
</table>
</form>
You don't need that nested for iterating k,v. I just tried this:
View:
def testme(request):
comments = []
comments.append({'user': 2, 'comment': 'cool story bro'})
comments.append({'user': 7, 'comment': 'yep. cool story'})
extra_context = {
'comments': comments
}
return render_to_response('testapp/testme.html', extra_context )
Template:
{% if comments %}
<b>Comments:</b>
<ul>
{% for comment in comments %}
<li>{{ comment.comment }} (id {{ comment.user }})</li>
{% endfor %}
</ul>
{% else %}
<b>No comments</b>
{% endif %}
"for k(k=key), v(v=value) in object.items"
All that is saying is to iterate over every key value pair i.e. such as name = models.CharField(max_length=50) in object.items. Your view has returned context for object.items which each item is a model instance and has a set of k,v pairs associated with it.
Looks like your question just about html markup.
Try this:
<tbody>
{% for obj in comment %}
<tr class="{% cycle 'odd' 'even' %}">
{% for key,val in obj.items %}
<td>{{val}}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
or this:
<tbody>
{% for obj in comment %}
<tr class="{% cycle 'odd' 'even' %}"><td>
{% for key,val in obj.items %}
{{val}}<span> </span>
{% endfor %}
</td> </tr>
{% endfor %}
</tbody>