Flask WTForms new inputs are not overwriting prepopulated data upon submission - python

I have a flask WTForms form which I am prepopulating with fields from my DB. From there I want to enable the user to update the values of any fields if they choose and re-insert this into the database. The specific issue I'm having with the below sample code is that when I submit the form, there is no data seen in the form.data dictionary (printed on line 18). Those fields are empty even though I've typed information into them. My guess is that form.field1.data is still holding the value it did from the database (line 11), and not taking in the data which the user has typed in.
However I cannot figure out how to otherwise structure the form in order to handle this. code below, thanks
#hp_blueprint.route('/formpage',methods=['GET','POST'])
def build_form():
#setup the QualitativeForm with values from the DB as placeholders
with sfsql_engine.connect() as conn:
df = pd.read_sql("SELECT * FROM MY_TABLE WHERE 1=1",conn)
if len(df) == 0:
form = QualitativeForm()
else:
form = QualitativeForm()
form.field1.data = df['field1'].values[0]
form.field2.data = df['field2'].values[0]
form.field3.data = df['field3'].values[0]
#write to DB upon submission
if form.is_submitted() and form.validate():
#WHEN I PRINT THIS OUT, IT DOES NOT HOUSE ANY OF THE DATA THAT I JUST TYPED IN
print(form.data)
print("the form update worked properly")
field1 = form.field1.data
field2 = form.field2.data
field3 = form.field3.data
with sfsql_engine.connect() as conn:
conn.execute("INSERT INTO MY_TABLE(field1,field2,field3) VALUES (%s,%s,%s)",
field1,field2,field3)
print("inserts ran correctly")
return redirect('/formpage')

For me it looks like you are overwriting the values of the form in your else statement - the code will be executed both in the "get" and in the "post" case. Therefore, I would change the order of both blocks and rewrite it like this:
#hp_blueprint.route('/formpage',methods=['GET','POST'])
def build_form():
form = QualitativeForm()
#write to DB upon submission
if form.is_submitted() and form.validate():
#WHEN I PRINT THIS OUT, IT DOES NOT HOUSE ANY OF THE DATA THAT I JUST TYPED IN
print(form.data)
print("the form update worked properly")
field1 = form.field1.data
field2 = form.field2.data
field3 = form.field3.data
with sfsql_engine.connect() as conn:
conn.execute("INSERT INTO MY_TABLE(field1,field2,field3) VALUES (%s,%s,%s)",
field1,field2,field3)
print("inserts ran correctly")
return redirect('/formpage')
#setup the QualitativeForm with values from the DB as placeholders
with sfsql_engine.connect() as conn:
df = pd.read_sql("SELECT * FROM MY_TABLE WHERE 1=1",conn)
if len(df) > 0:
form.field1.data = df['field1'].values[0]
form.field2.data = df['field2'].values[0]
form.field3.data = df['field3'].values[0]
# return the template with the form or continue with the code...

Related

Python/Flask/SQLite App validating against a different table before creating record in another table but not rendering final HTML

My app is/isn't writing to the DB under the right conditions so that's all working fine. It's checking one table for PSIReg number and if it exists in pharmaValidate table and if it exists, writing the record into pharmacies table.
The last little step where it renders a page in the case of the reg number being invalid is returning:
TypeError: The view function for 'PharmaReg' did not return a valid response. The function either returned None or ended without a return statement.
The desired behaviour is that it renders PharmaRegFail.html in the case of invalid PSIReg number and the record not writing to the DB (the latter part is already happening)
#app.route('/PharmaReg', methods=["POST", "GET"])
def PharmaReg():
msg = "msg"
with sqlite3.connect("mypharmaSQLite3.db") as con:
if request.method == "POST":
try:
PSIReg = request.form["PSIReg"]
PharmaName = request.form["PharmaName"]
PharmaPhone = request.form["PharmaPhone"]
PharmaAddress = request.form["PharmaAddress"]
PharmaEmail = request.form["PharmaEmail"]
realPharma = con.execute('select * from pharmaValidate where PSIReg = ?', [PSIReg])
validPharma = realPharma.fetchone()
if validPharma:
with sqlite3.connect("mypharmaSQLite3.db") as con:
cur = con.cursor()
cur.execute("INSERT into pharmacies (PSIReg, PharmaName, PharmaPhone, PharmaAddress, PharmaEmail) values (?,?,?, ?, ?)", (PSIReg, PharmaName, PharmaPhone, PharmaAddress, PharmaEmail))
con.commit()
msg = "Pharmacy successfully registered"
con.close()
return render_template("successRegPharm.html", msg=msg)
except:
return render_template("PharmaRegFail.html")
#app.route('/pharmaRegFail.html')
def pharmaRegFail():
return render_template("pharmaRegFail.html")

how do you auto generate a random ID for an SQLite database table

Im in the process of creating a website with python flask and html. I want it to have a register, login, edit, delete, and home page. I want to store the users login data in an sqlite database that can then be called to veify the login of the user. in order to have different users have the same username and/or password, I need to give each user a unique ID. I use this ID in the url, and I want the user to be able to use this ID for other things in the website. because of this, when a new user is added I need to give them a random (unique) ID (probably 8 digits). I saw a bunch of stuff about AUTO INCRAMENT being random, but I didnt understand it very much, and I tried it, and it gave me consecutive numbers (which is not what I want) I also tried RANDOM() and RAND() but they both threw syntax errors. can anyone tell me how to generate an sqlite column for an random unique 8 digit ID?
here's what I have:
schema.sql
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INTEGER PRIMARY KEY --insert random generator here,
username TEXT NOT NULL,
password1 TEXT NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
heres the python that runs the schema:
init_db.py
import sqlite3
connection = sqlite3.connect('database.db')
with open('schema.sql') as f:
connection.executescript(f.read())
cur = connection.cursor()
cur.execute("INSERT INTO users (username, password1) VALUES (?, ?)",
('user1', 'pass1')
)
cur.execute("INSERT INTO users (username, password1) VALUES (?, ?)",
('user2', 'pass2')
)
connection.commit()
connection.close()
thanks in advance for any help
okay.
Ive fixed this by generating a random number in the python code. when a user registers, I take their username and password, then generate a random number between 10000000 and 99999999. then I check if its in the database already, and if so, generate another one, until I generate a unique number. then I add username, password and ID to the database at the same time.
heres what I have now
(disclaimer: i am only showing the relevant code, so some of it might not make sense)
CREATE TABLE users (
id INTEGER,
username TEXT NOT NULL,
password1 TEXT NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
the init_db.py is the same,
heres the python:
from flask import Flask, render_template, url_for, request, flash, redirect, abort#imports
import sqlite3
import random
app = Flask(__name__)
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
def get_username(usernamex):#def and pass usernamex
validated_uname = False#reset progress variable
conn = get_db_connection()#connect to database
cur = conn.cursor()#create a cursor
try:
cur.execute('SELECT * FROM users WHERE username = ?',(usernamex,))#select the row in the users table where username == the usernamex variable
uname = cur.fetchone()[1]#uname = the second column of that row
validated_uname = True#update progress variable
except:#if the above failed: (most likely because usernamex was not in the database):
validated_uname = False#reset progress variable
if validated_uname == True:#if the try function passed:
return(uname)#update uname and send it back
conn.commit()#commit and close database
conn.close()
def get_password1(password1x):#def and pass password1x
validated_upass = False#reset progress variable
conn = get_db_connection()#connect to database
cur = conn.cursor()#create a cursor
try:
cur.execute('SELECT * FROM users WHERE password1 = ?',(password1x,))#select the row in the users table where password1 == the password1x variable
upass = cur.fetchone()[2]#upass = the third column of that row
validated_upass = True#update progress variable
except:
validated_upass = False#reset progress variable
if validated_upass == True:#if the try function passed:
return(upass)#update upass and send it back
conn.commit()#commit and close database
conn.close()
app.config['SECRET_KEY'] = '013ecbdd4aae3899c7feed1bf36dee4e'#secret key
#app.route("/register", methods=('GET', 'POST'))#url, and pass the get and post vaiables to make forms
def register():
if request.method == 'POST':#when request method is post in the html page: #(after they press submit)
usernamex = request.form['username']#take the username entered from html
password1x = request.form['password1']#same for pass1 and pass2
password2x = request.form['password2']
if not usernamex:#if nothing was entered for username:
flash('Username is required!')#error message
elif not password1x:#if nothing was entered for pass1:
flash('Password is required!')#error message
elif not password2x:#if nothing was entered for pass2:
flash('Valdiated password is required!')#error message
elif password1x != password2x:# if pass1 and pass2 dont match:
flash('Passwords do not match!')#error message
else:#otherwise
conn = get_db_connection()#connect to database
cur = conn.cursor()#create cursor
loop = True
while loop == True:
rand_id = random.randint(10000000, 99999999)#generate random number (8 digits)
try:
cur.execute('SELECT * FROM users where id = ?',(rand_id,))#select the row in the users table where id == the rand_id variable
r_id = cur.fetchone()[0]#r_id = the first column from that row ## this is just here to throw the error
except:
cur.execute('INSERT INTO users (id, username, password1) VALUES (?, ?, ?)',(rand_id, usernamex, password1x))#make a new row, and put in ID, username and password1 in their respective places
loop = False#break the loop
conn.commit()#commit and close database
conn.close()
id = rand_id#for the home url
#id = home_id(usernamex, password1x)#id = [call the home_id function {pass usernamex and password1x}]
return redirect(url_for('home', id=id))#go to the home page and pass id for the url
return render_template('register.html', title = 'Register')#render the template from register.html
thanks for everyones help :)

How can I make to make a complex query for my login system?

I want a login system which relates to a register database I made
I am trying to make a complex query which takes the user input:
Entry(self.root,
textvariable=self.username) ##There is more but I want this to be as minimal as possible
Entry(self.root,
textvariable=self.password,
show="*")
This user input then gets compared with the one in the database.
This is where I am finding it diffucult:
def login(self):
con = sqlite3.connect("register.db") ##The database which I want to open and compare user inputs to
c = con.cursor()
c.execute("SELECT * FROM register")
slist = c.fetchall()
values = [row[0] for row in slist]
values2 = [row[1] for row in slist]
if self.username.get() == values and self.password.get()==values2:
command=self.invcon ##A external thing I want to open if the user enters the data in correctly
else:
messagebox.showerror("Error","Error"parent=self.root)
con.commit()
con.close()
The error which is now happening is instead of opening the new window it moves into the else and pops up with the error box.
Database
The SQL "SELECT username * FROM register" should be "SELECT * FROM register".
Also values and values2 are list, so the comparison between a string (self.username.get() or self.password.get()) and a list will always be False.
However, you don't need to select all records from the table, just select the record with the username and password is enough:
def login(self):
con = sqlite3.connect("register.db") ##The database which I want to open and compare user inputs to
c = con.cursor()
# assume the fields required are 'username' and 'password'
# change them to suit your table definition
c.execute("SELECT 1 FROM register WHERE username = ? AND password = ?", (self.username.get(), self.password.get()))
result = c.fetchone() # get the record if any
if result:
# record found
command=self.invcon ##A external thing I want to open if the user enters the data in correctly
else:
# record not found
messagebox.showerror("Error", parent=self.root)
con.close()
I don't understand all of the errors but when selecting something from a table (in this case 'register') you can either select things by listing them up like:
c.execute("SELECT username, password ... FROM register")
or you simply select everything:
c.execute("SELECT * FROM register")
In this case you did both ("SELECT username * FROM ...") which is why there could be an error.

How to use flask variable in calling SELECT query in MariaDB

What is the correct syntax for calling a SELECT query in MariaDB from a Registration Form.
Specifically, in the WHERE clause. I've been looking all over the net to debug this and it does not seem to work (semantically).
Here is the code in my python flask.
#app.route('/check_email', methods = ['POST', 'GET'])
def chck_Email():
if request.method == 'POST':
visEmail = request.form['email']
conn = mariadb.connect(**config)
print(f"WE ARE CONNECTED ORAYT")
# create a connection cursor
cur = conn.cursor()
# execute an SQL statement
try:
print(visEmail)
#sql = " INSERT INTO visitor (Visitor_ID, Visitor_Name) VALUES( NULL, '{}')".format(Visitor_ID, Visitor_Name)
current_Email= cur.execute("SELECT user_Email FROM user_account WHERE user_Email = ?",(visEmail,))
print(current_Email)
if current_Email != None:
print('Email Invalid: Email already exists!')
form = Registration_Form()
exists = {
"email_exists": True
}
return render_template(exists,'register.html', form = form )
""The visEmail is the variable that is supposed to be holding the email address given by the user upon clicking submit, the program then checks in the database if the given email address already exists in the DB.
I printed the data in the visEmail variable to see the string(Which is fine), but the execution in the database returns me with "None" (It should not be returning a None since I already have the given email address on the DB). It is supposed to return the error "Email Already exists"
THank you very much
You're not fetching the row of results. cur.execute() doesn't return anything, you have to call cur.fetchone() to get the results, and assign that to current_Email.
try:
print(visEmail)
#sql = " INSERT INTO visitor (Visitor_ID, Visitor_Name) VALUES( NULL, '{}')".format(Visitor_ID, Visitor_Name)
cur.execute("SELECT user_Email FROM user_account WHERE user_Email = ?",(visEmail,))
current_Email = cur.fetchone()
print(current_Email)
if current_Email != None:
print('Email Invalid: Email already exists!')
form = Registration_Form()
exists = {
"email_exists": True
}
return render_template(exists,'register.html', form = form )

Django write in database when form is submit

i want to use html form to be able to send back information to my view.py, the goal is to get the data, use it as arguments in a call to a stored procedure.
def mouvementCreation(request):
idMI = 0
especes = TbEspece.objects.order_by('id')
#Get Mouvement informations
#Connection to 'erp-site' DB
cursor = connections['erp-site'].cursor()
try:
#Get Produits list from Espece
query = "{CALL SP_webGET_PRODUIT_FROM_ESPECE(%s,%s,%s,%s,%s)}"
arguments = (2016, 'C', 0, 10, 'A',)
cursor.execute(query, arguments)
produits = dictfetchall(cursor)
#Get Transporters list
cursor.execute("{CALL SP_webGET_TRANSPORT}")
transporters = dictfetchall(cursor)
#Get Livreur list
cursor.execute("{CALL SP_webGET_LIVREUR}")
livreurs = dictfetchall(cursor)
finally:
cursor.close()
cursor = connections['site'].cursor()
try:
#Get Circuit list
cursor.execute("{CALL SP_webGET_CIRCUIT_FOR_MVT}")
circuits = dictfetchall(cursor)
#Get Source list
cursor.execute("{CALL SP_webGET_SOURCE_FOR_MVT}")
mvtsources = dictfetchall(cursor)
#Get Dest list
cursor.execute("{CALL SP_webGET_DEST_FOR_MVT}")
destinations = dictfetchall(cursor)
#Get PontBascule list
cursor.execute("{CALL SP_webGET_PBASCULE}")
pontBascules = dictfetchall(cursor)
finally:
cursor.close()
reg_normes = TbRegauxnormes.objects.all()
ordreexecs = TbOrdreexecution.objects.all()
form = mouvementForm(request.POST or None)
if form.is_valid():
pont = form.cleaned_data['pont']
dateheure = form.cleaned_data['dateheure']
poid = form.cleaned_data['poid']
dsd = form.cleaned_data['dsd']
typepesee = form.cleaned_data['typepesee']
#Connection to 'erp-site' DB
cursor = connections['pontbascule'].cursor()
try:
#Get Produits list from Espece
query = "{CALL SP_ADD_MANUAL_PESEE(%s,%s,%s,%s,%s, %s,%s,%s,%s,%s, %s,%s,%s,%s,%s, %s,%s,%s,%s,%s, %s,%s)}"
arguments = (pont, '11', dateheure, poid, dsd,typepesee, '','','','','','','','','','','','','','','','')
cursor.execute(query, arguments)
finally:
cursor.close()
return render(request, 'mouvementCreation.html', {'form': form, 'especes' : especes, 'produits' : produits, 'transporters' : transporters, 'livreurs' : livreurs, 'circuits' : circuits, 'mvtsources' : mvtsources, 'destinations' : destinations, 'pontBascules' : pontBascules} )
The stored procedure is supposed to create a new entry.
What i want to do, but i'm not sure if possible would be :
Fill form => retrieve data in view => call stored procedure with the retrieved data => get the ID of the new entry so the user can be redirected to a another view that take the id in url parameters.
Would this be possible to do ?
Edit : I managed to get the post request working aswell as my stored procedure, my problem is now for the last part, redirecting the user on the right page after submiting the form.
the current page is /gestion_mouvement/mouvementCreation and i want the user to be redirected on /gestion_mouvement/mouvementDetails/{{ID}}
Problem is it seem that the query is too slow, because by the time i submit the form the user gets redirected to /gestion_mouvement/mouvementDetails/
and not recieving the ID.
What about creating a new cursor to fetch your last id created?
cursor.execute("SELECT max(id) from MANUAL_PESEE")
return {rec[0] for rec in cursor}
I've had the same issue recenly. Here is what I did.
Query concerned object model just after insert (after form.save()) and get the max(id) generated
form.save()
#mynewid = Msg.objects.all().order_by("-id")[0].id
mynewid = Msg.objects.latest('id').id
return redirect('/msg/{0}/edit/'.format(mynewid))

Categories