Access these dictionary values in flask template - python

My Template is outputting the below. It doesnt pull in any of the queried values, but the page loads fine and doesnt fail, but it doesnt show any of the values.
I double checked the query in a mysqlmonitor, and it pulls 3 records as it should.
<li></li>
In the templates/index.html I have:
{% for blogpost in blogposts %}
<li>{{blogpost[0]}}</li>
{% else %}
<li>no blog posts right now...</li>
{% endfor %}
app.py has this:
import pymysql.cursors
app = Flask(__name__)
connection = pymysql.connect(host='localhost', user='myuser', port=3306, password='mypass', db='mydb', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor)
#app.route('/', methods=('GET', 'POST'))
def email():
form = EmailForm()
curs = connection.cursor()
curs.execute("SELECT post_title, post_name, YEAR(post_date) as YEAR, MONTH(post_date) as MONTH FROM mydb.wp_posts WHERE post_status='publish' ORDER BY RAND() LIMIT 3")
blogposts = curs.fetchall()
if request.method == 'POST':
return render_template('index.html', form=form, blogposts=blogposts)
if __name__ == '__main__':
app.run()
UPDATE I think my for() is not working correctly, because when i update in the template i get all the data like:
[{u'MONTH': 12, u'YEAR': 2016, u'post_name': u'data is here', u'post_title': u'data is here'},
{u'MONTH': 12, u'YEAR': 2016, u'post_name': u'data is here', u'post_title': u"data is here"}]
How can i access this data in my flask template ?
Thank you so much!

Try finding out what is being sent to the template. Add print(blogposts) to the email function - just below the if request.method == 'POST': line and see what information it gives you.
If blogposts is a list of dictionaries, then you cannot access them by number. You need to use the name of the key. For example, you will need to change blogpost[0] to blogpost['name']. With Flask's templates you can also use the dot notation, so the blogpost name would become blogpost.name.

#app.route('/get', methods=['POST','GET'])
def requestCustomerDataFromTestForm():
data={'id':1, 'name':'Josh'}
return render_template("index.html", data = data)
In index.html
{% if data %}
<h1>{{data['id']}}</h1>
<h1>{{data['name']}}</h1>
{% endif%}
Or.. you can also iterate
<table class="table table-striped" >
<thead>
<tr>
<th scope="col">id</th>
<th scope="col">name</th>
</tr>
</thead>
<tbody>
{% for key, value in data.items() %}
<tr>
<th scope="row">{{ key }}</th>
<td>{{ value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
Or, to display all data with their index
{% if data %}
<p>{{data}}</p>
{% endif %}

Related

Query and display one row based on user input in jinja

I want to print one table row based on the user input. I am getting the user input (id) via HTML and Python, here:
html file:
<tbody class="table-group-divider">
{% for course in user.courses %}
<tr>
<!-- here an ID gets rendered from the table, and user clicks on it -->
<td>{{ course.course_name }}</td>
<td class="align-middle">
{% for student in course.students %}
<span>{{ student.student_name }}</span><br>
{% endfor %}
</td>
<td>{{ course.course_day }} {{ course.course_time }}</td>
<td>{{ course.course_language }}</td>
</tr>
{% endfor %}
</tbody>
app.py:
#app.route('/course_detail/<id>', methods=["GET", "POST"])
#login_required
def course_detail(id):
return render_template("course_detail.html", user=current_user, id=id)
My logic is to loop through the table, and if id provided by user matches id (primary key) in table, I found what I want to display, and then display it. However, my attempt does not print anything:
<!-- setting the ID from url/html, basically what user clicked -->
{% set id = id %}
{% for course in user.courses %}
{% if course.id == id %}
<p>im working</p>
{% endif %}
{% endfor %}
I get the id from user, but I can't seem to compare it with course.id so I could display the whole row. Is there a problem with my if statement?
Edit: If I hardcode the if statement to be for example {% if course.id == 2 %} (or any other valid course.id from the table), the information gets printed with no issues.
While I'm not sure why the original proposition doesn't work, I managed to reach my goal via querying my database in app.py, not my html file.
#app.route('/course_detail/<id>', methods=["GET", "POST"])
#login_required
def course_detail(id):
# query the id in db
db_id = Course.query.filter_by(id=id).first()
# save all info into variables
db_course_name = db_id.course_name
db_course_language = db_id.course_language
db_course_day = db_id.course_day
db_course_time = db_id.course_time
db_hourly_rate = db_id.hourly_rate
# send the variables and print them in html
return render_template("course_detail.html", user=current_user, pageid=db_id, db_course_name=db_course_name, db_course_language=db_course_language, db_course_day=db_course_day, db_course_time=db_course_time, db_hourly_rate=db_hourly_rate)
Then I simply printed the variables using double curly braces. Not sure if this is the best design, but it certainly feels better than my previous attempt.

Handling WTF form With for Loop correctly

Hello all I am new to flask I am just creating a basic table with DB data as S.no & Name & filling this with some random data of 10 users , Now I am query Db & displaying this list on HTML page in a table , on the HTML page I have added an extra column which takes input from WTF form Select field with option as YES & NO & Pending now the issues I am getting is on the HTML page select column If I select Yes as option & submit all other below row are getting this value , similarly If I select Pending On first & submit all row get pending How can I fix this kindly pardon my english
# for wtf-forms
class inputform(FlaskForm):
userinput = SelectField(choices=[('Yes'), ('No'),('Pending')])
Submit = SubmitField(label="Click to Submit")
#route
#app.route('/', methods=['GET', 'POST'])
def index():
form = inputform()
dbdata = mydb.query.all()
if form.validate_on_submit():
usernameinput = form.userinput.data
print(f"usernameinput {usernameinput}")
return render_template('index.html', userdata=dbdata, form=form)
On HTML
<form action="" method="post">
{{ form.hidden_tag() }}
<table class="table table-bordered ">
<thead>
<tr>
<th class="">S.No</th>
<th class="">name</th>
<th class="">Select</th>
</tr>
</thead>
<tbody>
{% for x in userdata %}
<tr>
<td>{{loop.index}}</td>
<td>{{x.user_name}}</td>
<td>{{form.userinput}}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{form.Submit()}}
</form>

How to display database on web framework?

I want to display the content of the database from .db file on web framework using flask module. However, only the row title is able to be displayed on the web framework. The content of the database from the .db file couldn't load out on the web framework. Anyone can help me with this? Thanks.
This is my code:
from flask import Flask, render_template
import sqlite3
app = Flask(__name__)
def connect_db(db):
con = sqlite3.connect(db)
return con.cursor()
#app.route('/')
def index():
db ='mcu_aurix_git.db'
cur = connect_db(db)
cur.execute("SELECT * FROM mcu_aurix")
data = cur.fetchall()
return render_template('flask.html', rows=data)
if __name__ == "__main__":
app.run(debug=True)
flask.html:
<table class="table table-hover">
<thead>
<tr>
<th>project</th>
<th>branch</th>
<th>id</th>
<th>number</th>
<th>subject</th>
<th>owner_name</th>
<th>owner_email</th>
<th>owner_username</th>
<th>url</th>
<th>commitMessage</th>
<th>createdOn</th>
<th>lastUpdated</th>
<th>open</th>
<th>status</th>
<th>current_date</th>
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
<td>{{row.project_name}}</td>
<td>{{row.branch_id}}</td>
<td>{{row.id_id}}</td>
<td>{{row.num_number}}</td>
<td>{{row.subject_name}}</td>
<td>{{row.owner_name}}</td>
<td>{{row.owner_email}}</td>
<td>{{row.owner_username}}</td>
<td>{{row.url_name}}</td>
<td>{{row.commitMessage_name}}</td>
<td>{{row.num_createdOn}}</td>
<td>{{row.num_lastUpdated}}</td>
<td>{{row.num_open}}</td>
<td>{{row.status_name}}</td>
<td>{{row.current_date}}</td>
</tr>
{% endfor %}
</tbody>
</table>
Is there anything missing in my code? Hopefully anyone can help me on this. Thanks in advance!
You are not passing rows variable to the html page.
return render_template('flask.html', data=data)
You are only passing data variable.
If you want to use rows inside your html page, you need to use
return render_template('flask.html', rows=data)
Also one more thing,
{{row.project_name}}
You cannot get the value of project_name like this, you need to use index value (col. no. starting from 0). Like,
{{row[0]}}
Instead of manually creating <td> for each col value, you can just use the below tbody code.
<tbody>
{% for row in rows %}
<tr>
{% for col in row %}
<td> {{ col }} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
Hope it helps!

How to pass a Mongo Cursor object to a Jinja template?

I have a Mongo database and I'd like to make a script that performs a query and passes the results to an html file.
This rendered html file will be used as the html body of an email I will send to my colleagues.
However the template is not rendered, here is what I've got
My html looks something like this:
<table>
{ %for q in query %}
<tr>
<td>{{ q['containers'] }} </td>
<td>{{ q['cases'] }} </td>
<td>{{ q['gross_weight'] }} </td>
<td>{{ q['volume'] }} </td>
</tr>
{ %endfor% }
</table>
While my script looks like this:
from pymongo import MongoClient, ASCENDING
from jinja2 import Template
def main():
client = MongoClient()
collection = client.supplyChain['commonRegimes']
parameters = {
'delivery_to_warehouse':None,
'regime':{'$in':['10', '91']}
}
query_result = collection.find(parameters).sort('eta_warehouse', ASCENDING)
templatefile = open('D:/myScripts/ccreport/reports/templates/nextArrivals.html').read()
template = Template(templatefile)
message = template.render(query = query_result)
if __name__ == '__main__':
main()
I get the error:
jinja2.exceptions.UndefinedError: 'q' is undefined
I would appreciate any help.
Ok I realized it was a syntax error in the for statement, It should be:
{% for q in query %}
{% endfor %}}

flask-wtf same form on same page using for loop

I'm brand new to programming. I came up with a project to help me learn and I'm stuck already. I'm using Flask, Flask-SQLAlchemy and Flask-wtf.
I'm trying to create a club attendance system that lists members and checks them off if they are present and logs the amount they paid (either $15 for 1 lesson, or $25 for the week). I have a table that I populate from my database that looks like this:
I want to click on submit to mark the person as present but this ticks the checkbox for everyone in the list and sets the amount paid to the same for everyone.
I have tried lots of things. I have seen similar issues here and people suggesting using FieldList and FormField - I tried this with no luck. Here is my Form code:
class MemberForm(Form):
form_id = HiddenField()
member_id = DecimalField('id')
member_name = StringField('name')
attend_date = StringField('date', default=todays_date())
is_here = BooleanField('here')
has_paid = SelectField('Amount', choices=[(15, '15'), (25, '25')])
submit = SubmitField("Submit")
def __init__(self, *args, **kwargs):
super(MemberForm, self).__init__(*args, **kwargs)
read_only(self.member_name)
My controller code:
#app.route('/', methods=['GET', 'POST'])
def home():
members = Member.query.order_by(Member.name).all()
form = MemberForm()
if request.method == 'POST': # TODO form validation and database stuff
print('got this far')
print(form.data)
return render_template('index.html', title='Tong Long',
today=todays_date(), members=members,
form=form)
and the jinja2 template part:
<table width="483" border="1">
<tbody>
<tr>
<th width="271"><strong>Member</strong></th>
<th width="152"><strong>Grade</strong></th>
<th><strong>Last Seen</strong></th>
<th width="38"><strong>Paid?</strong></th>
<th><strong>Is Here?</strong></th>
<th>Submit</th>
</tr>
{% for member in members %}
<form action="" method="post" name="{{ member.id }}">
<tr>
<td>{{form.member_name(value=member.name)}}</td>
{% for g in member.grade %}
<td>{{ g.grade }}</td>
{% endfor %}
<td>{{ form.attend_date }}</td>
<td>{{ form.has_paid }}</td>
<td>{{form.is_here}}</td>
<td>
{{ form.submit }}
</td>
</tr>
</form>
{% endfor %}
</tbody>
</table>
Viewing the rendered HTML I can see that all the fields have the same id.
I'm starting to think this can't be done with WTForms. Will I need to use javascript perhaps (something I know nothing about). Or manually create the forms rather than using WTF? Any help appreciated!
This is very late, but perhaps it is helpful to somebody.
What calabash is doing, is create one single form and then display it multiple times in the template.
However, to achieve the desired outcome (independend forms with independend submit buttons), multiple forms need to be created within the route function. They can be passed as a list to the template and then looped over. (A simpler solution would be one form with one submit button and dynamically created "lines" for each member. See FieldList...)
Logic:
def home():
members = Member.query.order_by(Member.name).all()
forms = []
for member in members:
form = MemberForm(prefix=member.name)
form.member_name.data = member.name
forms.append(form)
# validation:
for form in forms:
if form.submit.data and form.validate_on_submit():
# do_something here for each form, e.g. write to database
return render_template('index.html', title='Tong Long',
today=todays_date(),
forms=forms,
members=members)
The different forms need to have individual prefixes. They need to be validated individually and it needs to be checked which submit-button was used.
Note: It is perhaps not a good idea to use a form field for the name, as that information is already known from the members database entry and it might not be intended to change it here. A simple text label would make more sense in that case.
The table rows in the template could look like this:
{% for form in forms %}
<form action="" method="post">
{{ form.hidden_tag() }}
<tr>
<td>{{ form.member_name }}</td>
<td>{{ members[loop.index0].grade }}</td>
<td>{{ form.attend_date }}</td>
<td>{{ form.has_paid }}</td>
<td>{{ form.is_here }}</td>
<td>{{ form.submit }}</td>
</tr>
</form>
{% endfor %}

Categories