<table style="width:100%", border="1">
{% for item in items %}
<tr>
<td>{{Description[item]}}</td>
<td>{{Location[item]}}</td>
<td>{{Status[item]}}</td>
</tr>
{% endfor %}
</table>
I am trying to create a table using this for loop, the variables are being passed through in the flask framework, 'items' will always be the same length as the three lists (Description, location and status).
I am aware of the question below:
How to build up a HTML table with a simple for loop in Jinja2?
but I can not see how my code here differs to the working answer to this question, is it because I am using a list instead of a dictionary ?
This is the flask framework, where the lists
are created an passed through using render template:
def index():
description = []
location = []
status = []
imix80m = ''
imix = ''
with open('behavepretty.json') as a:
data = json.load(a)
for n in range(0,len(data)):
i = 0
for i in range(0, len(data[n]['elements'])):
x = data[n]['elements'][i]['name']
description.append(x)
y = data[n]['elements'][i]['location']
location.append(y)
z = data[n]['elements'][i]['status']
status.append(z)
n = 0
for n in range(0,len(data)):
if n == 0:
imix80m = data[n]['status']
elif n == 1:
imix = data[n]['status']
a.close()
return render_template('trial.html', Description = description, Location= location, Status = status, result1 = imix80m, result2 = imix, jfile = data, items = description)
You just need a loop counter:
<table style="width:100%", border="1">
{% for item in Description %}
<tr>
<td>{{Description[loop.index0 ]}}</td>
<td>{{Location[loop.index0]}}</td>
<td>{{Status[loop.index0]}}</td>
</tr>
{% endfor %}
</table>
Or, you could pack the 3 into a list of lists:
my_list = [[Description0, Location0, Status0], [Description1, Location1, Status1], ...]
Then:
{% for item in my_list %}
<tr>
<td>{{ item[0] }}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
</tr>
{% endfor %}
Or, more robustly, a list of dictionaries:
my_list = [
{
"description" : xxx,
"location" : yyy,
"status" : zzz
},
{
"description" : www,
"location" : eee,
"status" : rrr
},
...
]
Then:
{% for item in my_list %}
<tr>
<td>{{ item.description }}</td>
<td>{{ item.location }}</td>
<td>{{ item.status }}</td>
</tr>
{% endfor %}
Related
I am stuck trying to get my flask input function to work. I am trying to complete the CS50 2020 finance problem. Documentation for the problem can be found here. The code block bellow is the error message I get in the console when I try to use the index function is run. The api key I am using is valid and when inserting the whole url for the get request I get the expected information. Code may be somewhat messy, I have not cleaned it up and optimized it yet, because I can't get it to work.
DEBUG: SELECT quantity FROM oStocks WHERE userID = 5 AND stock = 'AAPL'
DEBUG: Starting new HTTPS connection (1): cloud.iexapis.com:443
DEBUG: https://cloud.iexapis.com:443 "GET /stable/stock/GOOGL-AF/quote?token=<MY_API_KEY> HTTP/1.1" 200 None
I have tried all I could think of to try and fix this error. changed and unchanged nearly everything about the lookup function. I can't seem to find what is wrong. Can someone please point me in the right direction. Thank you
flask index:
#app.route("/")
#login_required
def index():
userid = session["user_id"]
owned = db.execute("SELECT stock FROM oStocks WHERE userID = :userid", userid=userid)
OwnedStocks = []
for row in owned:
OwnedStocks.append(row["stock"])
stockInfo = {}
for item in OwnedStocks:
itemInfo = lookup(item)
tmpQuantity = db.execute("SELECT quantity FROM oStocks WHERE userID = :userid AND stock = :stock", userid=userid, stock=item)
quantity = tmpQuantity[0]["quantity"]
sharePrice = itemInfo["price"]
name = itemInfo["name"]
value = quantity * sharePrice
stockInfo[item] = {}
stockInfo[item]['symbol'] = item
stockInfo[item]['name'] = name
stockInfo[item]['shares'] = quantity
stockInfo[item]['price'] = sharePrice
stockInfo[item]['value'] = value
return render_template("portfolio.html", stocks=stockInfo)
Lookup Function:
def lookup(symbol):
"""Look up quote for symbol."""
# Contact API
try:
api_key = os.environ.get("API_KEY")
response = requests.get(f"https://cloud.iexapis.com/stable/stock/{urllib.parse.quote_plus(symbol)}/quote?token={api_key}")
response.raise_for_status()
except requests.RequestException:
return None
# Parse response
try:
quote = response.json()
return {
"name": quote["companyName"],
"price": float(quote["latestPrice"]),
"symbol": quote["symbol"]
}
except (KeyError, TypeError, ValueError):
return None
Portfolio html:
{% extends "layout.html" %}
{% block title %}
Portfolio
{% endblock %}
{% block main %}
<div>
<table class="table table-hover">
<thead>
<tr class="font-weight-bold">
<th scope="col">Symbol</th>
<th scope="col">Name</th>
<th scope="col">Shares</th>
<th scope="col">Price</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
{% for stock in stocks %}
<tr>
<th scope="row">{{ stock['symbol'] }}</th>
<td>{{ stock['name'] }}</td>
<td>{{ stock['shares'] }}</td>
<td>{{ stock['price'] }}</td>
<td>{{ stock['total'] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
I have found the solution, now finding it I feel dumb having looked in all the wrong places so long. My mistake was in iterating and calling values from a dictionary passed into a flask template. After much search I ended up realizing and fixing my problem while going through camposha.
My original method was:
{% for stock in stocks %}
<tr>
<th scope="row">{{ stock['symbol'] }}</th>
<td>{{ stock['name'] }}</td>
<td>{{ stock['shares'] }}</td>
<td>{{ stock['price'] }}</td>
<td>{{ stock['total'] }}</td>
</tr>
{% endfor %}
However the proper way to achieve my goal was:
{% for stock, value in stocks.items() %}
<tr>
<th scope="row">{{ value['symbol']['stock'] }}</th>
<td>{{ value['name'] }}</td>
<td>{{ value['shares'] }}</td>
<td>{{ value['price'] }}</td>
<td>{{ value['value'] }}</td>
</tr>
{% endfor %}
I aslo made some adjustments to my index:
def index():
userid = session["user_id"]
owned = db.execute("SELECT stock, quantity FROM oStocks WHERE userID = :userid", userid=userid)
stockInfo = {}
for item in owned:
print(item)
itemInfo = lookup(item['stock'])
quantity = item['quantity']
name = itemInfo['name']
sharePrice = float(itemInfo['price'])
value = quantity * sharePrice
stockInfo[item['stock']] = {}
stockInfo[item['stock']]['symbol'] = item
stockInfo[item['stock']]['name'] = name
stockInfo[item['stock']]['shares'] = quantity
stockInfo[item['stock']]['price'] = sharePrice
stockInfo[item['stock']]['value'] = value
return render_template("portfolio.html", stocks=stockInfo)
I am struggling to display two columns (resultlist) in seperate columns. Right now when i return result list its showing in a tuple. When i try to index the for loop(to remove the tuple) with i[0] in the HTML file but i get the first character which is the "("
current output:
column1
('123456', '150.92')
('49815', '70.43')
('19971', '39.35')
If i try to index the for loop in html, current output:
column1
(
(
(
expected output:
Column1 Column2
123456 150.92
49815 70.43
19971 39.35
Current python file:
def subtractboth(alloclist, statementlist):
resultlist = []
for i, j in zip(statementlist, alloclist):
if i[0] == j[0]:
results = float(j[1]) - float(i[1])
if results >= 0:
results = i[0], "{:.2f}".format(results)
print(" ".join(results))
resultlist.append(str(results))
return resultlist
#app.route('/results', methods=['GET', 'POST'])
def main():
connect()
masteracct = request.args.get('masteracct')
cashdt = request.args.get('cashdt')
billdt = request.args.get('billdt')
allocation(connect(), cashdt, masteracct)
statement(connect(), billdt, masteracct)
a = subtractboth(statement(connect(), billdt, masteracct), allocation(connect(), cashdt,
masteracct))
html = render_template('test_results.html', a=a)
return html
HTML:
<table>
<th>Column 1</th>
<th> Column 2</th>
{% for i in a %}
<tr>
<td>{{i}}</td>
<td>{{i}}</td>
</tr>
{% endfor %}
</table>
The Jinja2 template for displaying a table with 2 columns should look like this:
<table>
<tr>
<th>column1</th>
<th>column2</th>
</tr>
{% for v1, v2 in a %}
<tr>
<td>{{ v1 }}</td>
<td>{{ v2 }}</td>
</tr>
{% endfor %}
</table>
The variable a should be a sequence of pairs.
Here is my code:
phones = Customer.objects.filter(active=True).values('name')\
.annotate(count = Count('phone',filter=Q(phone__model__icontains=model_list[0]))
.annotate(count1 = Count('phone',filter=Q(phone__model__icontains=model_list[1]))
.annotate(count2 = Count('phone',filter=Q(phone__model__icontains=model_list[2]))
.annotate(count3 = Count('phone',filter=Q(phone__model__icontains=model_list[3]))
.annotate(count4 = Count('phone',filter=Q(phone__model__icontains=model_list[4]))
........
html
{% if phones %}
{% for phone in phones %}
<tr>
<td>{{ phone.name }}</td>
<td>{{ phone.count }}</td>
<td>{{ phone.count1 }}</td>
<td>{{ phone.count2 }}</td>
<td>{{ phone.count3 }}</td>
<td>{{ phone.count4 }}</td>
</tr>
{% endfor %}
{% enfif %}
My model_list still has many models. What should I do to simplify these using for loop?
If my model_list has 100 models, this will be very complicated.
I've tried this:
for i in range(len(model_list)):
phone= Customer.objects.filter(active=True).values('name')\
.annotate(count = Count('phone',filter=Q(phone__model__icontains=model_list[i]))
html
{% if phones %}
{% for phone in phones %}
<tr>
<td>{{ phone.name }}</td>
<td>{{ phone.count }}</td>
</tr>
{% endfor %}
{% endif %}
But the result is not what I want, because I only get one of the data.
For example :model_list[0]
Do like this to query for counts:
phones = Customer.objects.filter(active=True).values('name')
for idx, model in enumerate(model_list):
counts = {'count%s' % idx : Count('phone',filter=Q(phone__model__icontains=model)}
phones = phones.annotate(**counts)
Then you would need to pass a range of models to the template (say in models_idx_range as context parameter models_idx_range=range(models_count)) and iterate over counts:
{% if phones %}
{% for phone in phones %}
<tr>
<td>{{ phone.name }}</td>
{% for idx in models_idx_range %}
<td>{{ getattr(phone, 'count%s' % idx) }}</td>
</tr>
{% endfor %}
{% endif %}
I'm not a django expert but i think this is your error:
phone = Customer.objects.filter(active=True).values('name')
for i in range(len(model_list)):
phone= phone.annotate(count = Count('phone',filter=Q(phone__model__icontains=model_list[i]))
You always override your phone with the last value from the for-loop
Try this one
phones = Customer.objects.filter(active=True).values('name')\
.annotate(count = Count('phone',filter=Q(phone__model__icontains=[i for i in model_list]))
If I made a set of code like this...
object_data = {}
object = Object.objects.all()
for o in object:
ratings = ObjectRating.objects.filter(recipe=r)
counter = 0
ratings_sum = 0
for s in ratings:
counter += 1
ratings_sum += s.rating
rating_average = ratings_sum / counter
object_data[`o.id`] = (o, rating_average,)
data = {
'search_by' : search_by,
'object' : object_data
}
If I pass the data dictionary to the page (render_to_response(page, data, context_instance=RequestContext(request))), how do I get the data from both parts of the tuple in the template.
This is how I thought I had to do it...
{% for o in object %}
<tr><td>{{ o.0.name }}</td><td>{{ o.0.description }}</td><td>{{ o.0.other_col }}</td><td>{{ o.0.another_col }}</td><td>{{ o.1 }}</td></tr>
{% endfor %}
This is driving me insane and any insight will be helpful. This is Django 1.6 (I know I need to move on, so do not mention that in your answer).
Why not just add rating_average as an attribute to your object?
for o in object:
... # calculate rating average for this object
o.rating_average = ratings_sum / counter
data = {
'search_by' : search_by,
'object' : object
}
{% for o in object %}
<tr><td>{{ o.name }}</td>
<td>{{ o.description }}</td>
<td>{{ o.other_col }}</td>
<td>{{ o.another_col }}</td>
<td>{{ o.rating_average }}</td>
</tr>
{% endfor %}
Like this example:
class HomeView(generic.TemplateView):
template_name = '_layouts/index.html'
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
mydict = {'wat': 'coo'}
context['mydict'] = mydict
return context
Template:
{% for key, value in mydict.items %}
{{ key }} : {{ value }}
{% endfor %}
Basically, what I want to do is have the template system loop through two independent lists to fill two columns of a table. My approach was to use an index list (numList) as a way to access the same index of the two lists. I tried using the dot notation for list index lookup within a template loop but it doesn't seem to work in the loop. Any ideas on how I can remedy this?
numList = [0, 1, 2, 3]
placeList = ['park', 'store', 'home', 'school']
speakerList = ['bill', 'john', 'jake', 'tony']
<table>
<tr>
<th>Location</th>
<th>Time</th>
<th>Speaker</th>
</tr>
{% for num in numList %}
<tr>
<td>{{ placeList.num }}</td>
<td>1:30</td>
<td>{{ speakerList.num }}</td>
</tr>
{% endfor %}
</table>
The easiest thing is probably to combine your lists in python and then just look through the combined list in the template:
combinedList = [(placeList[i],speakerList[i]) for i in range(4)]
{% for entry in combinedList %}
<tr>
<td>{{ entry.0 }}</td>
<td>1:30</td>
<td>{{ entry.1 }}</td>
</tr>
{% endfor %}
Or for transparency, you could make combinedList a list of objects or dictionaries for example:
combinedList = [{'place':placeList[i],'speaker':speakerList[i]} for i in range(4)]
{% for entry in combinedList %}
<tr>
<td>{{ entry.place }}</td>
<td>1:30</td>
<td>{{ entry.speaker }}</td>
</tr>
{% endfor %}
You could aggregate these two lists in one.
For example:
yourlist = [('park','bill'),('store','john'),('home','jake'),...]