Is there a pattern for dealing with query params in a flask rest server? I know I can create a sql query word for word using string manipulation in python, but I find that to be ugly and error prone, I was wondering if there is a better way. Here's what I have:
param1 = request.args.get('param1', type = int)
param2 = request.args.get('param2', type = int)
if param1 is not None:
if param2 is not None:
cursor.execute("SELECT * FROM table WHERE p1 = %s AND p2 = %s", (str(param1), str(param2)))
else:
cursor.execute("SELECT * FROM table WHERE p1 = %s", (str(param1),))
else:
if param2 is not None:
cursor.execute("SELECT * FROM table WHERE p2 = %s", (str(param2),))
else:
cursor.execute("SELECT * FROM table")
It's easy to see the number of possible SQL statements is 2 to the number of parameters, which grows out of control... so, again, without using string manipulation to custom build the sql query, is there an idiom or pattern that is used to accomplish this in a more elegant way? Thanks.
Loop through your parameters.
params = []
for i in range(1, HoweverManyParamsYouNeed):
params.append(request.args.get('param' + str(i), type = int))
s = ""
for i in range(1, len(params)):
if params[ i ] is not None:
if not s:
s = "p" + str(i) + " = " + str(params[ i ])
else:
s = s + " AND p" + str(i) + " = " + str(params[ i ])
full = "SELECT * FROM table"
if s:
full = full + " WHERE " + s
cursor.execute(full)
You might need to correct this code, since I do not have a way to run it.
I suggest using ORM(https://en.wikipedia.org/wiki/Object-relational_mapping) instead of raw sql queries.
First you need install flask-sqlalchemy (https://flask-sqlalchemy.palletsprojects.com/)
Then define your model
class MyModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
column1 = db.Column(db.Integer)
column2 = db.Column(db.Integer)
Let's say you have your filter lookup somewhere
allowed_filters = {"column1", "column2"}
Finally instead of cursor you can use SQLAlchemy's ORM to retrieve your filtered objects.
query = MyModel.query
for field, value in request.args.items():
if field in allowed_filters:
query = query.filter(getattr(MyModel, field) == value)
my_object_list = list(query.all())
If you really want to create your queries manually you can always iterate over args:
where_clause = ""
params = []
for field, value in request.args.items():
if field in allowed_filters:
if len(where_clause) > 0:
where_clause += " AND "
where_clause += "{} = %s".format(field)
params.append(value)
if len(where_clause) > 0:
cursor.execute("SELECT * FROM table WHERE {}".format(where_clause), tuple(params))
else:
cursor.execute("SELECT * FROM table")
Related
conn = mysql.connector.connect(
host="localhost",
user="root",
passwd="12123123412"
database='newdb')
cur = conn.cursor()
xx_zz = self.screen.get_screen('end').ids["rgr"].text
ee_zz = self.screen.get_screen('end').ids["gfd"].text
qur = f"SELECT * FROM (%s) WHERE bedrooms = '(%s)' "
val = (xx_zz, ee_zz)
cur.execute(qur, val)
records = cur.fetchall()
I suggest that we use a function to create the query string using match-case. This will avoid any risk of SQL injection as we are not using the string provided by the front end.
You will need to modify and complete the option values and table names and decide whether there should be a default table name or no result if the option provided is not found.
Obviously this code has not been tested.
def makeQuery( option ):
match option:
case 'option1':
return f"SELECT * FROM table_name_1 WHERE bedrooms = '(%s)' "
case 'option2':
return f"SELECT * FROM table_name_2 WHERE bedrooms = '(%s)' "
case _:
return f"SELECT * FROM default_table_name WHERE bedrooms = '(%s)' "
conn = mysql.connector.connect(
host="localhost",
user="root",
passwd="12123123412"
database='newdb')
cur = conn.cursor()
xx_zz = self.screen.get_screen('end').ids["rgr"].text
ee_zz = self.screen.get_screen('end').ids["gfd"].text
qur = makeQuery(xx_zz )
val = ( ee_zz )
cur.execute(qur, val)
records = cur.fetchall()
In textInput (field) you use hint_text to show a placeholder in a text field(input).
I have the following code where the ph variable does not interpolates with the select query.
I am just trying to access http://localhost/testing?phone_number=1234567890 it returns like () rather particular record of the phone number.
#app.route("/testing",methods=['GET')
def testing():
ph = request.args.get('phone_number')
cur = mysql.connection.cursor()
cur.execute('''SELECT * FROM client_base where phone_number={}'''.format(ph))
results = cur.fetchall()
return ''' {} '''.format(results)
Abetter solution is using prepared statements like below
#app.route("/testing",methods=['GET')
def testing():
ph = request.args.get('phone_number')
cur = mysql.connection.cursor()
cur.execute('''SELECT * FROM client_base where phone_number=%s''',(ph,))
results = cur.fetchall()
return ''' {} '''.format(results)
I'm writing a code to generate n-grams for every record in the table by reading a specific column.
def extract_from_db(inp_cust_id):
sql_db = TatDBHelper()
t_sql = "select notes from raw_data where customer_id = {0}"
db_data = sql_db.execute_read(t_sql.format(inp_cust_id))
for row in db_data:
text = row.values()
bi_grams = generate_ngrams(text[0].encode("utf-8"), 2)
print bi_grams
def generate_ngrams(sentence, n):
sentence = sentence.lower()
sentence = re.sub(r'[^a-zA-Z0-9\s]', ' ', sentence)
tokens = [token for token in sentence.split(" ") if token != ""]
ngrams = zip(*[tokens[i:] for i in range(n)])
return [" ".join(ngram) for ngram in ngrams]
I'm getting the output like:
['i highly', 'highly recommend', 'recommend it']
['the penguin', 'penguin encounter', 'encounter was', 'was awesome']
I want the output to look like below, can anybody help me to get this.
['i highly',
'highly recommend',
'recommend it',
...
]
creat another list all_ngrams, and keep appending the values to it , using .extend(), and finally you will have all the ngrams in one list.
Try this :
def extract_from_db(inp_cust_id):
sql_db = TatDBHelper()
t_sql = "select notes from raw_data where customer_id = {0}"
db_data = sql_db.execute_read(t_sql.format(inp_cust_id))
all_ngrams = []
for row in db_data:
text = row.values()
bi_grams = generate_ngrams(text[0].encode("utf-8"), 2)
all_ngrams.extend(bi_grams)
print all_ngrams
i just wrote a small script to port sqlite table to mysql but im realy not sure if i did right.
Im atleast sure, it works to the mysql-connection part, so atleast it already builds mysql connection.
from __future__ import with_statement
import sqlite3
import os
import pymysql
addonPath = "Path-To-SQLITe-Database"
addonPathOrginal = -"Path-To-Database.ini"
connection = sqlite3.connect(os.path.join(addonPath, "db.sqlite"))
#connection.row_factory = sqlite3.Row
connection.text_factory = str
cursor = connection.cursor()
sqliteexecute = cursor.execute
fetchall = cursor.fetchall
databaseinfo = os.path.join(addonPathOrginal, "database.ini")
d = {}
with open(databaseinfo, "r") as fs:
for l in fs.readlines():
l = l.strip(" ").strip("\n")
obj = l.split("=")
if len(obj) != 2: continue
if obj[1] == "": continue
d[obj[0]] = obj[1]
mysqlcon = pymysql.connect(**d)
mysqlcursor = mysqlcon.cursor()
execute = mysqlcursor.execute
execute("SET ##autocommit=1;")
execute("SET sql_notes = 1;")
execute("SET FOREIGN_KEY_CHECKS = 0;")
tablename = "jumptimes" # Convert Table 'jumptimes'
sqliteexecute("SELECT * FROM sqlite_master WHERE type='table' AND tbl_name='%s'" tablename)
#sqliteexecute("SELECT jumptimes FROM sqlite_master")
for x in fetchall():
print "Table: %s" % tablename
#if tablename == "sqlite_sequence": continue
sqliteexecute("SELECT * FROM %s" % tablename)
stuff = fetchall()
if len(stuff) == 0: continue
string = ("%s," * len(stuff[0]))[:-1]
print "Table %s, %i elements, length of string %i" % (tablename, len(stuff),len(stuff[0]))
for y in range(0, len(stuff), 5):
mysqlcursor.executemany("REPLACE INTO " + tablename + " VALUES (" + string + ")", stuff[y:y+5])
connection.close()
execute("SET FOREIGN_KEY_CHECKS = 1;")
mysqlcon.commit()
mysqlcon.close()
database.ini
host=""
user=""
passwd=""
db=""
I'm struggling with the formatting on a mysql query and I was hoping you could point me in the right direction. Here are the queries
sql = "SELECT price FROM inventory WHERE card_name = %s AND card_set = %s"
sql_rare = "SELECT rarity FROM inventory WHERE card_name = %s AND card_set = %s"
sql_count = "SELECT count(*) FROM inventory WHERE card_name = %s AND card_set = %s
When I run the following code, utilizing the sql_count query, i get an error saying:
File "C:\Users\Spencer\Desktop\Python Programs\PythonMTG\Revision3AutoAndManual\51515\magicassistantcsv.py", line 264, in output_card
for row in getmtgprice.query(sql_count, ([card_name, set_name])):
TypeError: query() takes exactly 4 arguments (3 given)
Here is the code producing this error:
getmtgprice = PriceCheck()
for row in getmtgprice.query(sql_count, ([card_name, set_name])):
if row[0] ==0:
priced_card = '0.00'
And here is the PriceCheck function:
class PriceCheck(object):
def __init__(self):
self.conn = MySQLdb.connect(host='localhost', user='root', passwd='', db='mscan')
self.c = self.conn.cursor()
def query(self, arg, cardname, setname):
self.c.execute(arg, cardname, setname)
return self.c
def __del__(self):
self.conn.close()
Do you see where I went wrong?
Your query method takes separate arguments for cardname and setname, not a list containing both. So, instead of:
for row in getmtgprice.query(sql_count, ([card_name, set_name])):
You should have:
for row in getmtgprice.query(sql_count, card_name, set_name):