HTML FLASK using {% for %} in JSON data - python

I am using google firebase which returns data in JSON, compared to SQLAlchemy which returns it in something else.
In SQLAlchemy, I can fetch a database, pass it as a variable in flask render_template, and do something like this to display all the tables.
{% for Order in query %}
<tr>
<td>{{ Order.uuid }}</td>
<td>{{ Order.costusd }}</td>
<td>{{ Order.costcry }}</td>
<td>{{ Order.orderinfo }}</td>
<td>{{ Order.userpaid }}</td>
</tr>
{% endfor %}
If I attempt this with firebase/JSON data, it will display empty tables (the amount of tables that I have data in firebase) but with no data. I tried to do order['uuid']. etc for all of them, but that does not work either.
So, I am trying to display my database in the same way that SQLAlchemy can do it, but i am using a NOSQL database that is JSON.

This was a duplicate
Working code to translate the NoSQL data into jinja2 readable:
r = json.dumps(json_onject)
loaded_r = json.loads(r)
return render_template("report.html", items=loaded_r)

Related

passing variable to a table in flask

I am following this video and everything is working perfectly. The output of a SQL query is saved within a variable that I can call on in another .html page.
so my sql query is:
#app.route('/all_data')
def all_data():
customers = db.get_customers()
for customer in customers:
var = customers
return render_template('all_data.html',var=var)
When calling this {{var}} in all_data.html page the output is for a long tuple:
('name','email','comment','gender'),('name','email','comment','gender') etc etc
I am looking to put this {{var}} into a table instead?.. I but am hitting a brick wall in finding out how to do this?
any help would be much appreciated!
Assuming you're using Flask's default template engine (Jinja2), you can simple use a for loop to iterate over the elements of the collection inside the template. The syntax is:
{% for item in items %}
{{ item }}
{% endfor %}
So simply create an HTML table, and add a row for each item in your var variable.
IIRC, Jinja tuples act the same as Python's, so you can probably do something along the lines of:
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Comment</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
{% for current in var %}
<tr>
<td>{{ current[0] }}</td>
<td>{{ current[1] }}</td>
<td>{{ current[2] }}</td>
<td>{{ current[3] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
I haven't checked it (as I don't have a Flask project available right now), but if my memory serves me right, that's how I would do it
Here's a link to an usefull part of Jinja2's documentation
Also, what is this piece of code for ?
for customer in customers:
var = customers
You're iterating over each element of the list, but your never use the customer variable (containing the current element). Instead, you assign the var variable to the customers list multiple times. Assuming customers is a simple Python list, you could remove this loop and simply do return render_template('all_data.html',var=customers)

Flask+SQLAlchemy: How to show the latest entry in 1-to-many database

Sorry I couldn't come up with a clear title, I'm not exactly sure what it is called that I want to accomplish. Also english is not my first language so please bear with me.
I've set up a database with two tables "Sensors" and "SensorValues".
There should be a one-to-many relationship so that one sensor can have many readings but the readings can belong to only one sensor.
I'm using Flask and flask-sqlalchemy.
Database models:
class Sensor(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True, nullable=False,)
gpiopin = db.Column(db.INT, unique=False, nullable=False,)
stype = db.Column(db.String(20), unique=False, nullable=False,)
values = db.relationship('SensorValues', backref='author', lazy=True) #not a column in table, just backreference
def __repr__(self):
return f"Sensor('{self.name}', '{self.gpiopin}', '{self.stype}')"
class SensorValues(db.Model):
id = db.Column(db.Integer, primary_key=True)
reading = db.Column(db.String(64), unique=False)
timestamp = db.Column(db.DateTime, unique=False, nullable=False, default=datetime.utcnow)
sensor_id = db.Column(db.Integer, db.ForeignKey('sensor.id'), nullable=False)
def __repr__(self):
return f"Value('{self.reading}', '{self.timestamp}')"
Here's the flask route for home.html:
#app.route("/", methods=['POST', 'GET'])
def home():
sensors = Sensor.query.all()
posts = SensorValues.query.all()
return render_template('home.html', posts=posts, sensors=sensors, db=db)
How I generate the table in home.html
<tbody>
{% for sensor in sensors %}
<tr>
<td>{{ sensor.name }}</td>
<td>{{ sensor.gpiopin }}</td>
<td>{{ sensor.stype }}</td>
<td>{{ sensor.values.reading }}</td> <- Where I want the latest reading of the specific sensor in the SensorValues to appear
</tr>
{% endfor %}
</tbody>
Now, I have another table which lists all the readings and the names of the sensors they belong to.
It's basically a history and this way it works because I'm looping the SensorValues table directly.
{% for post in posts %}
<tr>
<td>{{ post.author.name }}</td>
<td>{{ post.author.stype }}</td>
<td>{{ post.reading }}</td>
<td>{{ post.timestamp }}</td>
</tr>
{% endfor %}
I tried to change the first loop to this:
{% for sensor in sensors %}
<tr>
<td>{{ sensor.name }}</td>
<td>{{ sensor.gpiopin }}</td>
<td>{{ sensor.stype }}</td>
{{ lastvalue = SensorValues.filter_by(sensor_id=sensor.id).last()}}
<td>{{ lastvalue.reading }}</td>
</tr>
{% endfor %}
Where I tried to make a filter query to the SensorValues table with the current sensor.id (the id of the Sensor the for loop is currently in) and logically I think that could work but the syntax is not correct. I got the Jinja error:
expected token 'end of print statement', got '='
Can I even do the query in the home.html or do I have to do it in the routes before the page is rendered?
The query in the view function needs to be updated to include information about the latest reading for the sensors before passing it in the template context.
Start out with writing the query in SQL and then convert it to its SQLAlchemy variant.
The SQL query to find the last sensor reading values is the following:
https://www.db-fiddle.com/f/5fXZyPiPYawc22ffMi2tYk/0
SELECT DISTINCT
s.*,
FIRST_VALUE(sv.reading) OVER (
PARTITION BY sv.sensor_id ORDER BY sv.timestamp DESC
) AS last_reading
FROM sensors AS s
JOIN sensor_values AS sv ON s.id = sv.sensor_id
Now, let's build the SQLAlchemy variant
import sqlalchemy as sa
sensors = Sensor.query.join(
SensorValues).with_entities(
Sensor,
sa.func.first_value(
SensorValues.reading).over(
partition_by=SensorValues.sensor_id,
order_by=SensorValues.timestamp.desc
).label('latest_reading'))
The Result rows returned from the above query are instances of KeyTuple and the latest_reading label should be available as a direct attribute of the sensor in the Jinja2 template.
{% for sensor in sensors %}
<tr>
<td>{{ sensor.Sensor.name }}</td>
<td>{{ sensor.Sensor.gpiopin }}</td>
<td>{{ sensor.Sensor.stype }}</td>
<td>{{ sensor.latest_reading }}</td>
</tr>
{% endfor %}
I'm not sure if I should edit this to the original post rather than posting it as an answer?
But anyways I got it working with:
{% for sensor in sensors %}
<tr>
<td>{{ sensor.name }}</td>
<td>{{ sensor.gpiopin }}</td>
<td>{{ sensor.stype }}</td>
{% set lastvalue = SensorValues.query.filter_by(sensor_id=sensor.id).order_by(SensorValues.timestamp.desc()).first() %}
<td>{{ lastvalue.reading }}</td>
</tr>
{% endfor %}
And of course I had to add SensorValues to the route:
#app.route("/", methods=['POST', 'GET'])
def home():
sensors = Sensor.query.all()
posts = SensorValues.query.all()
#lastvalue = SensorValues.query.filter_by(sensor_id=sensor.id).last()
return render_template('home.html', posts=posts, sensors=sensors, db=db, SensorValues=SensorValues
If there is a better way by all means show it, but for now it works.

Django - Too slow database record read

I have a database with about 1500 records about one class. I'm also using jQuery Datatables to list the records.
views.py:
records = Animal.objects.all()
return render(request, 'animals.html', {'records': records})
template:
{% for record in records%}
<tr>
<td>{{ record.id }}</td>
<td>{{ record.specie }}</td>
<td>{{ record.category}}</td>
<td>{{ record.quantity }}</td>
</tr>
{% endfor %}
But, it is very very slow. Even reducing the number of records to 100 it takes about 20~45 seconds to fully load a page. Doing the same select to find all 1500 records directly on database takes only 1 second.
As I am using jQuery DataTables to paginate and search the values, is there a way to improve this loading table time?
EDIT:
I used the django debug toolbar and I got these results:

Django: Accessing list attributes in template

I have a SQL query in a Django view and store the results in a variable. As far I know the result should be stored as a list.
def assignments(request):
cursor = connection.cursor()
cursor.execute("SELECT o.article_id, o.amount, m.id, o.create_date, m.status FROM orders o, producers p, machines ma, matches m WHERE ma.producer_id=1 AND m.machine_id = ma.id AND m.order_id = o.id")
articles = cursor.fetchall()
context = {"article_list": articles}
return render(request, 'assignments.html', context)
Then I want to transfer that data row by row in a table in my template.
{% block body %}
<div class="container">
<table class="table">
<thead>...</thead>
<tbody>
{% for articles in article_list %}
<tr>
<td>{{ articles.article_id }}</td>
<td>{{ articles.amount }}</td>
<td>{{ articles.id}}</td>
<td>{{ articles.create_date }}</td>
<td>{{ articles.status }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
Unfortunately the table is empty and is not showing any results.
The query itself should be fine. I tested the query in my database workbench and it is showing the correct results.
How can I access the data stored in variable articles from my template?
PS: I'm far from being a programmer. So I don't really know any programming concepts/language.
Any help is highly appreciated. Thanks!
You have a list of lists. Each element in articles_list is just a list of values from the database; it does not have any knowledge of attributes like "id" or "amount".
As Arpit says in the comments, you should be using Django models for this rather than raw SQL.

Unicode issues when requesting form

I'm using HTML, Flask and MYSQL to populate a table when the user first loads the page. The table displays all the rows along with a checkbox and when a user presses the submit button, I get the rows that were checked.
Current HTML code
{% for row in data %}
<tr>
<td><input type="checkbox" name="inputSelect" value="{{ row[0], row[3] }}"></td>
<td>{{ row[0] }}</td>
<td>{{ row[1] }}</td>
<td>{{ row[2] }}</td>
<td>{{ row[3] }}</td>
</tr>
{% endfor %}
However, when I try request.form['InputSelect'] on the flask side, it only gives me one result even if I click more than one checkbox.
What's the best way to create the table so that when I click multiple checkboxes, I can see all of them using request.form['InputSelect']
Flask use MultiDict. To get the list of items for a given key, you can use getlist() method.
Try this:
value = request.form.getlist('InputSelect')

Categories

Resources