How to pass variables in python flask to mysqldb? - python

Code in .py file:
cur = mysql.connection.cursor()
# Check if this user had voted for somebody
is_voted = cur.execute("SELECT TUTOR_VOTED FROM USERS WHERE USERNAME="+str(session["username"]))
session["username"] keep a user cookie. The user I already logged in names "admin"
But there might be something wrong with the MySQL command inside is_voted
Error:
MySQLdb._exceptions.OperationalError: (1054, "Unknown column 'admin' in 'where clause'")
But I got the correct return value while using
SELECT TUTOR_VOTED FROM USERS WHERE USERNAME='admin'
Is there anything wrong with my input format inside is_voted?

Your output string of the combination "SELECT TUTOR_VOTED FROM USERS WHERE USERNAME="+str(session["username"]) misses couple of single quote ''. You can change it to:
is_voted = cur.execute("SELECT TUTOR_VOTED FROM USERS WHERE USERNAME='%s'" % str(session["username"]))

Related

Updating a Table by using Sqlite3 Module in Python

I am working on a project where i need to update the password column of a user table pointing userid as the primary key, whenever the user reset his/her password. I am passing username and password to update_table function based on the values entered by the user from console and below is my code snippet -
def sql_update_table(conn, username, reset_password):
c = conn.cursor()
#value = (username, reset_password)
#c.execute('''UPDATE user SET password = ? WHERE userid = ? ''', value)
c.execute('''UPDATE user SET password = reset_password WHERE userid = username''')
conn.commit()
I tried both case passing values with a tuple as mentioned in # and directly as mentioned without a #. However, for first case, there is no error but the table is not getting updated with the new value of password and for later one i am getting below error -
sqlite3.OperationalError: no such column: reset_password
Please help me to solve this.
Thanks in advance !
Can you please try replacing
c.execute('''UPDATE user SET password = reset_password WHERE userid = username''')
with
c.execute('''UPDATE user SET password = ? WHERE userid = ? ''', (username,reset_password))

Accessing specific item in sqlite3 database when user and password matches

I've created a login GUI with sqlite in python and i've got it working correctly, however I want it to do something else as well when it logs in.
My sqlite database currently has the following columns;
Username, Email, Password, Workstation, Directory
I've found that you can take an item string in the table by using something like;
connection.fetchall()[index]
However, I don't know how to implement it into my code to check for the user that logged in.
username = "username"
password = "password"
# database information
connection = sqlite3.connect(databasepath+'\login.db')
result = connection.execute("SELECT * FROM USERS WHERE USERNAME = ? AND PASSWORD = ?", (username, password))
if (len(result.fetchall()) > 0):
#some code#
I want to access the 'Directory' item for the user that logged in

locating a password that corresponds to a username within an sqlite table

I am running a website using Flask microframework and sqlite3 to store user logins. Currently, I am having trouble with matching the username and password entered by the user from an HTML form, with the existing records within my database.
I am using the flask-login extension to help me with this, and when I try and match, I am receiving a TypeError:
list indices must be integers or slices, not str
here is my python code that is turning the SQLite table into a variable:
con = sql.connect("table.db")
cur = con.cursor()
cur.execute('SELECT * FROM users')
names = cur.fetchall()
I then have this code which is taking the password from the HTML form, and trying to match it with the password linked to the username in the table
user_name = request.form['username']
if request.form['password'] == names[user_name]['password']:
user = User()
user.id = user_name
flask_login.login_user(user)
this is what 'names' returns:
[(7, 'ValidName', 'ValidTest', 'User#test.com'), (8, 'User2', 'password2', 'User#test2.com')]
What needs to happen is the program will check the form input for 'password' and will match it with the 'password' that is related to the username. So as an example, if ValidName and ValidTest were entered into the form, they would be requested by the program, and matched with the records found in 'names'.
I assume you have not hashed your password which is something you should do. Without security in mind
here is my dirty approach
cur.execute('SELECT * FROM users WHERE name = %s AND password = %s', (request.form['username'], request.form['password']))
user = cur.fetchone()
This can be helpful
Here is the guilty: names[user_name]['password']
names is the return value of fetchall and hence is a plain list. To use it in above expression, it should be a mapping of mappings.
You should construct it that way:
names = {row[1]: {'id': row[0], 'password': row[2], 'mail': row[3]}
for row in cur.fetchall()}
But beware: this loads the full user database in memory. It only makes sense if you have few users...

SQL Query returning "None" instead of row

I'm working on a light login, and have a tabled titled Users. I'm trying to take my login form POST body and verify it across the database.
Values from form:
user = request.form['username']
password = request.form['password']
SQL Statement:
conn = sqlite3.connect(db)
cur = conn.cursor()
cur.execute("SELECT * FROM Users WHERE Username LIKE '(%s)'" % user)
row = cur.fetchone()
Users Table:
So on a POST request from my form, here is what is printed:
Print(user, password) = ph104694 Password123
Print(row) = None
So you can see the row is being returned as None when the data absolutely exists. If I change user to something I know is incorrect, I'm getting the same results, but if I change the table from Users to something like Users2 I'm met with a no table exists error which is fine. So despite matching data existing something about my statement isn't allowing it to produce that row. Any ideas?
You're search expression is evaluating to (ph104694) which clearly doesn't exist in the data you showed.
There is no reason to use the LIKE operator here and it probably runs counter to what you want to do (match the single record exactly matching the user ID that was entered).
This is the classic example of code that is subject to an SQL injection attack. You should never, never, ever use string interpolation to build an SQL string like this. Instead, use parameter substitution.
Taken all together, you want something like this:
cur.execute("SELECT * FROM Users WHERE Username = ?", [user])
Your query string evaluates to "SELECT * FROM Users WHERE Username LIKE '(ph104694)'".
Note the parentheses which aren't in the actual username.
Also, you almost certainly don't want to use LIKE.
What you want is "SELECT * FROM Users WHERE Username = 'ph104694'"
Which would create with "SELECT * FROM Users WHERE Username = '{user}'".format(user=user)
Also, you can (and should) parameterize this as
cur.execute("SELECT * FROM Users WHERE Username = :user", {user: user})

Querying in Python

I'm building a database on python 2.7 using sqlite3 and I have reached a small problem.
Basically I have two tables which each store the following information:
Tweet:
user_name,
tweet_time,
tweet_text
User:
user_name,
user_description,
user_followers,
user_verified,
user_location
I am trying to add a function which prompts the user to enter a string, and every row in both tables which contains the submitted string, which will be found in the tweet_text column, is deleted.
The problem I'm having is that the 'User' Table does not contain a column tweet_text so I'm not sure how to delete corresponding rows in this table without actually having to add a tweet_text column.
What I have so far is just a simple delete query on the 'Tweet' Table.
delete_string = raw_input("Which string would you like to be removed from your database?: ")
c.execute("DELETE FROM Tweet WHERE tweet_text LIKE ?", ('%'+delete_string+'%',))
I'm wondering if there is any way to delete the corresponding rows in the 'User' Table without having to explicitly include tweet_text as a column.
I'm relatively inexperienced on python and this is my first time using query writing so any help will be greatly appreciated!
Thanks in advance.
I just wrote this from my mind but try this query:
DELETE tweet, user
FROM Tweet tweet JOIN User user ON tweet.user_name = user.user_name
WHERE tweet.tweet_text LIKE ?;
Although what you're looking for is this, ON DELETE CASCADE.
That will automatically delete it from foreign key table, which will be your User table.
Make sure to enable foreign key support in SQLite
PRAGMA foreign_keys = ON;
According to your question, you may delete by querying the username using the tweet_text column but I do not believe you wish to delete the username if you have 2 tweets from the same user and you delete one.
I would probably suggest this:
# Fetch all users with a tweet_text that is similar to the delete_string
res = c.execute("SELECT user_name FROM Tweet WHERE tweet_text LIKE ?", ('%'+delete_string+'%',)).fetchall()
# If any user is found
if res:
# Get his username
user_name = res[0][0]
# Delete the tweet
c.execute("DELETE FROM Tweet WHERE tweet_text LIKE ?", ('%'+delete_string+'%',))
# If he has no more tweets in the database
if c.execute("SELECT 1 FROM Tweet WHERE user_name = ?", (user_name)).fetchone() is None:
# Delete the user.
c.execute("DELETE FROM User WHERE user_name = ?", (user_name))
First you fetch the user_name if the tweet exists
Then you delete the tweet
Then you check if there are more tweets from the same user.
If there are none you delete him from the database.
If you wish, you may support multiple users like so:
# Get all users with similar tweets
res = c.execute("SELECT user_name FROM Tweet WHERE tweet_text LIKE ?", ('%'+delete_string+'%',)).fetchall()
# If there are any
if res:
# Get their user names (make it a set to avoid repeated names)
user_names = set(u[0] for u in res)
# Delete all the similar tweets
c.execute("DELETE FROM Tweet WHERE tweet_text LIKE ?", ('%'+delete_string+'%',))
for user in user_names:
# Check for each user if he has more tweets in the database
if c.execute("SELECT 1 FROM Tweet WHERE user_name = ?", (user,)).fetchone() is None:
# If he has none, delete him.
c.execute("DELETE FROM User WHERE user_name = ?", (user_name))
UPDATE:
If you have the same amount of rows, you must have an identifier(rowid) which will tie the tweet and the user. Define the tweet database as so: (The important part is the identifier)
identifier INTEGER PRIMARY KEY AUTOINCREMENT,
user_name TEXT,
tweet_time DATETIME,
tweet_text TEXT
And the User database as so:
identifier PRIMARY KEY,
user_name TEXT,
user_description TEXT,
...
Upon inserting rows to the tweet database, use cursor.lastrowid in order to fetch the generated identifier and insert the generated identifier together with the user to the Users database. You should probably do it in the same transaction. Upon deleting, delete from both databases where the identifier is the same.
See this stackoverflow question and the sqlite documentation regarding rowid or identifier columns.
Here's an example:
# When adding
with connection:
cursor = connection.execute("INSERT INTO Tweet (user_name, tweet_time, tweet_text) VALUES (?, ?, ?)", (user, time, text))
rowid = cursor.lastrowid
cursor.execute("INSERT INTO User (identifier, user_name, user_description, ...) VALUES (?, ?, ?, ...", (rowid, user, desc, ...))
# When deleting
tweet_ids = c.execute("SELECT identifier FROM Tweet WHERE tweet_text LIKE ?", ('%'+delete_string+'%',)).fetchall()
if tweet_ids:
cursor.executemany("DELETE FROM Tweet WHERE identifier = ?", tweet_ids)
cursor.executemany("DELETE FROM User WHERE identifier = ?", tweet_ids)
# Or one line when deleting (I'm not sure if it works)
c.execute("DELETE tweet, user FROM Tweet tweet JOIN User user "
"ON tweet.identifier = user.identifier "
"WHERE tweet.tweet_text LIKE ?", ('%'+delete_string+'%',))

Categories

Resources