Problem of Flask append the result after render_template - python

I have a problem with my Flask Application which is the render_template always append the result
This is my code for Flask:
#app.route('/predict',methods=['POST'])
def predict():
if request.method == 'POST':
state2 = request.form['state']
with psycopg2.connect("host=localhost dbname=twitah user=amz password=admin1234") as conn:
with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur:
#negeri=state
cur.execute("SELECT id,textt FROM tweet WHERE state = '%s';"%state2)
rows = cur.fetchall()
#print ("# Individual row values accessed via column name:")
for i in range (cur.rowcount):
row = rows[i]
i=row['id']
u=row['textt']
idd.append(i)
dataa.append(u)
return render_template('masuk.html', id=idd,data=dataa)
After running the IP Address the output in masuk.html always append with the previous one when tried with another return value.

Where do you define your variables idd and dataa? I guess that they are defined as global variables, stay in namespace between requests and they grow in size when you do those append methods. You should put
idd = []
dataa = []
in your predict() function.

Related

Not able to reach generated lists in other .py file

I need some help to solve the problem :
I have two files : "main.py" and let's say "script.py"
The "script.py" contains a func() that generates variable amount of lists (programm uses Database, so amount of lists and data inside is vary):
def func():
try:
connect = psycopg2.connect(database = 'car_rental',
user = 'postgres',
password = 'datapass')
curs = connect.cursor()
#iteration that creates the list contains all models available for every single brand with name '{category}_{brand.lower()}'
# (in this case: economy_{brand.lower()})
temp_var = ''
for brand in economy_brands_list:
curs.execute("""SELECT DISTINCT model
FROM fleet
WHERE category = %s and brand = %s""", ('economy', f'{brand}'))
expres = [x[0] for x in curs.fetchall()]
temp_var+=f"economy_{brand.lower()} = {expres}\n"
exec(temp_var)
finally:
curs.close()
connect.close()
In "main.py" i want to use the list(s) generated in func(). So i imported func() to 'main.py', call the func(), but it gives the error instead.NameError : name 'economy_{brand}' is not defined. From the 'script.py' (which contains func()) the function works and i'm able to print the lists generated. How to make 'main.py' to define the lists generated in func()?
Thank You in advance.
To expand on Tierry Lathuille's answer, you may want something like this:
def func():
economy_brands = {}
try:
connect = psycopg2.connect(database = 'car_rental',
user = 'postgres',
password = 'datapass')
curs = connect.cursor()
#iteration that creates the list contains all models available for every single brand with name '{category}_{brand.lower()}'
# (in this case: economy_{brand.lower()})
temp_var = ''
for brand in economy_brands_list:
curs.execute("""SELECT DISTINCT model
FROM fleet
WHERE category = %s and brand = %s""", ('economy', f'{brand}'))
expres = [x[0] for x in curs.fetchall()]
economy_brands[f"economy_{brand.lower()}"] = expres
finally:
curs.close()
connect.close()
return economy_brands

flask - unable to run a variable to a list in for loop to store the sql database

I'm unable to loop through the "query" variable with the items list and push the code to database. but it is throughing an error ""ValueError: not enough values to unpack (expected 2, got 1)"", can someone check the code please?
#app.route('/', methods=['POST'])
def test():
if request.method == 'POST':
try:
query = request.form['url']
r = requests.get(query)
output = r.json()
items = output['result']
# # items = ['abc','bcd','cde','def'] # here items will be in list
for i in items:
user = User(listOfItems=items[i], query=query)
db.session.add(user)
db.session.commit()
responseBody = {'message': items}
return make_response(jsonify(responseBody))
except Exception, e:
return ('Oops!', e.__class__, 'occurred.')
else:
responseBody = {'message': 'failed'}
return make_response(jsonify(responseBody))
desired output in database:
listOfItems query time_stamp
abc example.com -date-
bcd example.com -date-
cde example.com -date-
def example.com -date-
xyz example1.com -datetime.now-
yza example1.com -datetime.now-
zab example1.com -datetime.now-
here,
query1: example.com returns ['abc','bcd','cde','def'] list items
query2: example1.com returns ['xyz','yza','zab'] list items
This part of the code has an issue. for i in items means the value at that index, not the index itself. So the first iteration will return 'abc' and so on.
for i in items:
user = User(listOfItems=items[i], query=query)
db.session.add(user)
db.session.commit()
Assuming that you want to have the values of the list and insert them, change the line to
user = User(listOfItems=i, query=query)
I found some problems:
you do not need the if request.method == 'POST' statement, you've already declared method in the route decorator.
for i in items returns each element from items, the i variable is not an index; so, user = User(listOfItems=items[i], query=query) is incorrect.
I'm not sure these will solve your problem or not; but if not, please show the output of items and output.

Storing dicts/namedtuple from DB-query in session-object in Flask throws "TypeError: can't pickle sqlite3.Row objects"

Working on my 1st baby project with Flask. It's a game and my goal is to store the user's current "live game" and "team"(group) in the session-dict, so I don't have to run the DB-query every time a route gets called (I can't think of any other way to 'centrally' store & pass around this data elegantly).
So I am doing that in my code "new_game" (attached) in lines 13 & 14. The get_db() function (found here: https://flask.palletsprojects.com/en/1.1.x/patterns/sqlite3/) returns a namedtuple - also attached my implementation of it.
These lines have led to my debugger dumping "TypeError: can't pickle sqlite3.Row objects". Now, I suspected that maybe namedtuple as a type is the problem and encapsulated the get_db() with dict(), but that didn't change anything.
Looks to me like a common thing with a very obvious solution for experienced folks... so any help/hints/background on this would be highly appreciated! ☺️
#app.route("/new_game", methods=["GET", "POST"])
#login_required
def new_game():
# get group_name from form & initiating user's turn
if request.method == "POST":
group_name = request.form.get("group")
row = query_db("SELECT * FROM groups WHERE group_name=? AND user_id=?",[group_name, session["user_id"]], one=True)
# new DB entry for new game
get_db().execute("INSERT INTO games (active, turn, group_name) VALUES (:active, :turn, :group_name)", {"active":1, "turn":row["turn"], "group_name":row["group_name"]})
get_db().commit()
#store user's live game and group in session
session["game"] = query_db("SELECT * FROM games INNER JOIN groups ON groups.group_name=games.group_name INNER JOIN users ON users.user_id=groups.user_id WHERE users.user_id=? AND games.active=?", [session["user_id"], 1], one=True)
session["gamegroup"] = query_db("SELECT * FROM groups INNER JOIN games ON games.group_name=groups.group_name INNER JOIN users ON groups.user_id=users.user_id WHERE groups.user_id=? AND games.active=?", [session["user_id"], 1], one=True)
return render_template("live_game.html", turn=row["turn"], round=1, isturn=True, group_name=group_name)
else:
return redirect("/new_game")
###########################################
def get_db():
db=getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect("ce.db")
db.row_factory = sqlite3.Row
return db
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv

Updating a specific row with Flask SQLAlchemy

I have this app with a profile and I want to update only a specific row based on its account id. Inserting the data works, but updating a specific row doesn't and I'm not sure which part is wrong with my code.
#app.route('/edit_parent/<int:acc_id>', methods=['GET','POST'])
def edit_parent(acc_id):
myParent = Parent.query.filter_by(acc_id=int(acc_id)).first()
if request.method == "POST":
myParent.fname_p = request.form['fname_p']
myParent.lname_p = request.form['lname_p']
myParent.bday_p = request.form['bday_p']
myParent.add_p = request.form['add_p']
db.session.commit()
print "hello success"
return redirect(url_for('parent', acc_id=int(acc_id)))
if request.method == "GET":
return render_template('edit_p.html', acc_id=int(acc_id))
It prints the "hello success" and redirects to the parent url but returns an error 302 and still no changes in the db.
I don't think you are updating a specific row at all, but instead you are just inserting new one each time with:
myParent = Parent(request.form['fname_p'], request.form['lname_p'],
request.form['bday_p'], request.form['add_p']).where(acc_id=acc_id)
db.session.add(myParent)`
So, what you are supposed to do instead is:
myParent = Parent.query.filter_by(acc_id=acc_id)
assuming your Parent db has the following attributes:
myParent.fname = request.form['fname_p']
myParent.lname = request.form['lname_p']
myParent.bday = request.form['bday_p']
myParent.add = request.form['add_p']
db.session.commit()
solved it by adding:
myParent = db.session.merge(myParent)
this way it merges the current session with the previous one. It still returns a 302 but the data on the db has been successfully updated.

Sqlalchemy not committing object changes to postgres DB

I am using the following passage of code:
#app.route('/budget_item/<int:budget_id>/edit', methods=['GET', 'POST'])
def budget_item_edit(budget_id):
budget_item = session.query(Budget).filter_by(id=budget_id).one()
print "Start EDIT sequence"
# Return form data from HTML initial load form
elif request.method == 'POST':
budget_amount_reallocated_total = budget_item.budget_amount_reallocated_total
#ORIGINAL BUDGET
if request.form['transaction_type'] == 'Original Budget':
#amount
if request.form['amount'] == "":
amount = 0
else:
amount = float(str(request.form['amount']))
budget_item = Budget(
#created_date = "",
budget_transaction_type = request.form['transaction_type'],
budget_line = request.form['budget_line'],
amount = amount,
description = request.form['description']
#date_received = request.form['date_received']
)
try:
count = 1
while count < 10000:
count += 1
#budget_line
setattr(budget_item,'budget_line'+str(count),request.form['budget_line'+str(count)])
#amount
setattr(budget_item,'amount'+str(count),float(request.form['amount'+str(count)]))
budget_amount_reallocated_total += float(request.form['amount'+str(count)])
setattr(budget_item, 'budget_amount_reallocated_total', budget_amount_reallocated_total)
#description
setattr(budget_item,'description'+str(count), request.form['description'+str(count)])
#date_received
setattr(budget_item,'date_received'+str(count),request.form['date_received'+str(count)])
session.commit()
except:
session.commit()
return redirect(url_for('budget_master'))
else:
print "I'm done! This is not a post request"
This block of code is setup to pass data from an HTML via a POST request an then update a corresponding object in the Postgres DB. I can confirm that the object queried from the DB "budget_item" is being updated by settattr. At the end of the passage, I use commit() to update the object; however, the database doesn't reflect the changes. Just to test to make sure things are flowing, I've tried session.add(budget_item) followed by session.commit() to make sure the connect to the DB is OK. That works. How do i update this budget_item object into the database? Any help is much appreciated.
i think that a simple
budget_item.budget_amount_reallocated_total = budget_amount_reallocated_total
session.add(budget_item)
session.commit()
is the right way to do it
To answer your question, to update the budget_item that already exists in the database you need to update the Budget instance that you retrieved from the database, i.e.
budget_item = session.query(Budget).filter_by(id=budget_id).one()
not the one that you have newly created with:
budget_item = Budget(...)
Here the first budget_item represents the row in the database, so this is the one to update. To that end you can replace the code that creates the second Budget instance with this:
budget_item.budget_transaction_type = request.form['transaction_type']
budget_item.budget_line = request.form['budget_line']
budget_item.amount = amount
budget_item.description = request.form['description']
Once you have finished updating the Budget instance you can call session.commit() to flush it to the database.
As mentioned in my comment to your question, it appears that you are trying to add a large number of additional attributes to budget_item all of which will be ignored by sqlalchemy unless they are defined in the mapping between the Budget instance and the Budget table.

Categories