Cannot insert integer to MySQL in python - python

In my flask application, I cannot insert user_id which I get from request.form
and it is an integer to MySQL. Here is my code:
from flask import Flask, jsonify, render_template
from flask import request
import socket
from flask_mysqldb import MySQL
app = Flask(__name__)
app.config['MYSQL_HOST'] = '192.168.0.101'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PORT'] = '3307'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'msblog_users'
mysql = MySQL(app)
#app.route("/create_post", methods = ['POST', 'GET'])
def create_post():
if request.method == 'GET':
return "You can only send post requests here!"
if request.method == 'POST':
user_id = request.form.get('user_id')
message = request.form.get('message')
cursor = mysql.connection.cursor()
cursor.execute('''INSERT INTO posts (user_id, post)VALUES (%s, %s)''', (int(user_id), message))
mysql.connection.commit()
cursor.close()
return "Done"
I get the following error:
TypeError: 'str' object cannot be interpreted as an integer
What should I do? I did lots of search but so far nothing!

The error comes from the int(user_id) part, specifically due to the value being None. You should first make sure it is a valid integer:
try:
user_id = int(request.form.get('user_id'))
except (ValueError, TypeError):
return <error 400>

The %s stands for string, if you want you want that parameters to be an integer, make it %i.
INSERT INTO posts (user_id, post)VALUES (%i, %s) ....
If the column post is a string / text column (varchar probably) you should also quote it as such.
cursor.execute("INSERT INTO posts (user_id, post) VALUES (%i , '%s')" % (1, 'string value')
By the way, this is the old way of formatting strings
The new way is doing this:
cursor.execute("INSERT INTO posts (user_id, post) VALUES ({}, '{}')".format(1, 'string value')
Or you can name the parameters:
"INSERT INTO posts (user_id, post) VALUES ({id}, '{str}')".format( str='string value',id=1)

Finally, I found the problem.
It's so strange!! the problem was not even related to the insert query. Take a look at the MySQL connection configuration part in my flask code, as you can see below:
app.config['MYSQL_HOST'] = '192.168.0.101'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PORT'] = '3307'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'msblog_users'
the port is written between quotations! it's a string but MySQL needs an integer value for the port to be able to connect!
here is the quick fix:
app.config['MYSQL_PORT'] = 3307
It took me a day to solve it!

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 pass a number larger than 9 to a psycopg2 select statement

I have a simple Flask app. The app connects with a database of movie reviews. I built a function to retrieve data which takes a max_count argument. but for some reason, I can only pass a number smaller than 10. The app works fine if I pass 3 or 9. Here is my code:
from flask import Flask, request
import requests
import psycopg2
from psycopg2.extras import RealDictCursor
import json
app = Flask(__name__)
#app.route('/')
def home():
return "Hello!"
#app.route('/get_total_data_count/<label>', methods=['GET'])
def get_total_data_count(label):
connection = psycopg2.connect(user="barmej", password="password", host="127.0.0.1", port="5432", database="labeling")
cursor = connection.cursor()
try:
if label == 'positive':
cursor.execute("SELECT * FROM data_labeling WHERE label_number = 0 limit 100;")
elif label == 'negative':
cursor.execute("SELECT * FROM data_labeling WHERE label_number = 1 limit 100;")
elif label == 'all':
cursor.execute("SELECT * FROM data_labeling;")
return "The count is " + str(cursor.rowcount)
except:
return "Error! type: positive, negative or all"
cursor.close()
connection.close()
#app.route('/get_data', methods=['GET'])
def get_data_test():
try:
connection = psycopg2.connect(user="barmej", password="password", host="127.0.0.1", port="5432", database="labeling")
cursor = connection.cursor()
max_count = request.args.get('max_count')
sort_order = request.args.get('sort_order')
if sort_order == 'ASC':
insert = "SELECT text FROM data_input ORDER BY ASC limit %s"
parameters = max_count
cursor.execute(insert, parameters)
result = cursor.fetchall()
elif sort_order == 'DESC':
insert = "SELECT text FROM data_input ORDER BY DESC limit %s "
parameters = max_count
cursor.execute(insert, (parameters))
result = cursor.fetchall()
dic = {}
dic['text'] = result
return dic
except:
return "Error!, make sure url include: a max count and either 'ASC' or 'DESC' Argument"
cursor.close()
connection.close()
if __name__ == "__main__":
app.run(debug=True, port=3000)
The call is done in python shell from the server:
>>> import requests
>>> param = {'max_count': 12, 'sort_order': 'ASC'}
>>> r = requests.get('http://127.0.0.1:3000/get_data', params=param)
>>> r.text
I tried the code without the exception and the error is:
psycopg2.errors.SyntaxError: syntax error at or near "%"\nLINE 1: SELECT text FROM data_input limit %s
The issue is how you're passing the parameter to .execute()
You need to pass a tuple like this:
cursor.execute(insert, (parameters,)) # a comma is necessary to make a tuple
Currently when there is multiple digits it thinks those are separate parameters.

How to fix {"message": "The method is not allowed for the requested URL." } for my post method?

This is the first time I'm creating an API for android retrofit. I modified this code according to the snippet I got online. The main functionality of the post method is to take the given parameters and store it in the sqlite3 database.
My schema of the following two tables:
sqlite> .schema spending
CREATE TABLE spending(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT ,
reason TEXT ,
amount INTEGER
);
CREATE TABLE receiving(
ID INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT ,
from_reason TEXT ,
amount INTEGER
);
from flask import Flask, request
from flask_restful import Resource, Api
from sqlalchemy import create_engine
from flask import jsonify
db_connect = create_engine('sqlite:///api.db')
app = Flask(__name__)
api = Api(app)
class AddSpending(Resource):
def add_spending(self):
try:
_json = request.json
_date = _json['date']
_reason = _json['reason']
_amount = _json['amount']
# validate the received values
if _date and _reason and _amount and request.method == 'POST':
#do not save password as a plain text
#_hashed_password = generate_password_hash(_password)
# save edits
sql = "INSERT INTO spending(date, reason, amount) VALUES(%s, %s, %d)"
data = (_date, _reason, _amount)
#conn = mysql.connect()
conn = db_connect.connect()
cursor = db_connect.cursor()
conn.cursor()
conn.execute(sql, data)
conn.commit()
#resp = jsonify('Spending added successfully!')
#resp.status_code = 200
return
else:
return 404
except Exception as e:
print(e)
finally:
cursor.close()
conn.close()
api.add_resource(AddSpending, '/spending_up',methods=['POST']) # Route_3
When a user passes data through this parameter. The data should be stored in the database
I think the problem is that you called you method as add_spending and shoud be named as post
change def add_spending(self) by def post(self)
the code for your api should look like that, without the methods='POST'
class AddSpending(Resource):
def post(self):
try:
_json = request.json
_date = _json['date']
_reason = _json['reason']
_amount = _json['amount']
# validate the received values
if _date and _reason and _amount and request.method == 'POST':
#do not save password as a plain text
#_hashed_password = generate_password_hash(_password)
# save edits
sql = "INSERT INTO spending(date, reason, amount) VALUES(%s, %s, %d)"
data = (_date, _reason, _amount)
#conn = mysql.connect()
conn = db_connect.connect()
cursor = db_connect.cursor()
conn.cursor()
conn.execute(sql, data)
conn.commit()
#resp = jsonify('Spending added successfully!')
#resp.status_code = 200
return
else:
return 404
except Exception as e:
print(e)
finally:
cursor.close()
conn.close()
api.add_resource(AddSpending, '/spending_up') # Route_3
UPDATE
I just tried with a code similar to yours and worked
ANOTHER UPDATE
your repo code

InternalError: (1054, u"Unknown column 'Ihe' in 'where clause'")

Below is a part of my python/pymysql code. I'm basically trying to retrieve data from a database using the input typed into a search box. I don't understand why the data typed in is coming across with this error. "Ihe" is simply a test hostname in my the database.
#app.route('/result',methods= ['POST', 'GET'])
def result():
if request.method == 'POST':
result = request.form['hostname']
cursor = connection.cursor()
query = ("SELECT * FROM StoryData WHERE hostName LIKE %s" % ( result))
cursor.execute(query)
search_for = cursor.fetchall()
for row in search_for:
ID = row['ID']
hName = row['hostName']
rName = row['reportName']
return render_template("result.html", search_for=search_for)
connection.close()
As written, this is a very dangerous SQL Injection vulnerability.
What happens when I submit a POST request with hostname set to
''; DROP TABLE StoryData;
?
Use parameterized queries instead of using Python string formatting. Assuming your paramstyle is format, you can pass the parameters to execute():
query = "SELECT * FROM StoryData WHERE hostName LIKE %s"
cursor.execute(query, (result, ))

Categories