How to create working like button in flask and sqlite3? - python

I am trying to create a social network using flask and sqlite3. I had created almost all the main things like post, edit post, delete post. But I also want to add the like button for every post. I had created like number(How many like this post got) and like button and it is working fine but If you like my post for the first time and again login your account then you can again like that post which you had already liked by your account.
I had an idea to save who liked my post but i don't know how to implement that exact code in my webapp.I am using sqlite3 so I am not finding any solution for this issue. I had found exactly same question for mysql or any other database but I had not for sqlite3.
Ok here is my idea,
I had already mentioned that I am using sqlite3 so I had created table like this:
conn=sqlite3.connect('data/detailpost.db')
c=conn.cursor()
c.execute("""CREATE TABLE postdetail(
name text,
address text,
post text,
post_date text,
secretcode text,
mainname text,
likes integer,
likers text)""")
conn.commit()
conn.close()
and If someone click like button(In template) then that will come in this part of back-end where I am getting liker mainname and oid number of that post.And this is the same back-end code which increase the like of the post. Like this
#app.route('/social/post/like',methods=['POST'])
def likedofsocial():
if request.method=='POST':
oid=request.form['oid']
mainusernameofliker=request.form['username']
conn=sqlite3.connect('data/detailpost.db')
c=conn.cursor()
c.execute("SELECT *,oid FROM postdetail WHERE oid="+oid)
alldata=c.fetchall()
for rec in alldata:
c.execute("""UPDATE postdetail SET
name=:name,
address=:address,
post=:post,
post_date=:datee,
secretcode=:secret,
mainname=:mainname,
likes=:likes
likers=:likers
WHERE oid=:num""",
{
'name':rec[0],
'address':rec[1],
'post':rec[2],
'datee':rec[3],
'secret':rec[4],
'mainname':rec[5],
'likes':(int(rec[6]+1)),
'likers':mainusernameofliker,
'num':oid,
})
conn.commit()
conn.close()
.....
Here in this above part I don't know how to save multiple mainusernameofliker inside likers beacause there will not be only one person who likes my posts.
Now I have only idea for front-end I had not tried any of the code which is mentioned below!! I just think following code could works fine
"For front-end check that likers data and
(% if (your mainusername is in that likers data ) %)
then show already liked(Liked) or disable like button
(% else (your username is not in that likers data) %)
then that show like or make clickable like button".
(% endif %)
Probably, I could get help as soon as possible and any help will be appreciated.

I think your main question is that how to store the multiple users who would like the post. It is very simple, you just need to create one more table maybe called postlikers. This table will reference primary keys of user and postdetail. Basically a many-to-many relationship between user and postdetail tables.
I will show you an example that how you can define the tables below:
import sqlite3
conn=sqlite3.connect('detailpost.db')
c=conn.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS user(
id INTEGER PRIMARY KEY,
name text)
""")
c.execute("""CREATE TABLE IF NOT EXISTS postdetail(
id INTEGER PRIMARY KEY,
name text,
address text,
post text,
post_date text,
secretcode text,
mainname text,
likes integer DEFAULT 0
)""")
c.execute("""CREATE TABLE IF NOT EXISTS postlikers(
id INTEGER PRIMARY KEY,
post_id INTEGER,
user_id INTEGER,
FOREIGN KEY(post_id) REFERENCES postdetail(id),
FOREIGN KEY(user_id) REFERENCES user(id)
)
""")
conn.commit()
conn.close()
# Add data
user_data = [('Carl'), ('Mel'), ('Bobby')]
post_data = [('first_post', 'whajjne', 'I love everything', 'dfweffwwffefe', 'secret', 'Carl', 0),
('second_post', 'whajjne', 'I love everything', 'dfweffwwffefe', 'secret', 'Mel', 0)]
conn=sqlite3.connect('detailpost.db')
c=conn.cursor()
for user in user_data:
c.execute('INSERT INTO user (name) VALUES (?);', (user,))
for post in post_data:
c.execute('INSERT INTO postdetail (name, address, post, post_date, secretcode, mainname,likes ) VALUES (?,?,?,?,?,?, ?);', post)
conn.commit()
conn.close()

Related

SQLAlchemy and foreign keys doesn't work when deleting rows

I have API - python script (using Flask and SQLite) which works with database with 3 tables.
Table Comany has relationship 1:N with table User. And table Company has relationshipt 1:N with table Keyword.
Now, if I will delete some company, I expect it will also delete all users who belong to company, as well as all keywords.
I have found, I have to turn on FOREIGN Keys, using these lines
#event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
if type(dbapi_connection) is sqlite3.Connection: # play well with other DB backends
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
However it will still only delete company, and foregin keys in rows of users as well as keywords of this company stay NULL.
E.g. Table User
ID, Name, Pass, FK_company_name
These are lines how I am deleting company
...
company_id = request.args.get('company_id')
company = Company.query.get(company_id)
db.session.delete(company)
db.session.commit()
...
Do I have to set something else?

How to show different data to different users in flask application?

I have created a flask application and using mysql as DB backend and this is used by multiple users simultaneously.
The problem I'm having is,In my homepage a select query is performed and data is displayed to the user but same data is showing to all users.it should be unique. I have tried to lock the row by using FOR UPDATE while selecting the row. I know that I'm not updating the row,so the transaction will be closed when the function ends and the row will be released from lock.
How to overcome this problem?
Expected output: Each user should get different data from the table.(Even when they refresh)
#is_logged_in
#app.route('/')
def index():
conn = mysql.connection
cur = conn.cursor()
cur.execute("select mylist ,myurl ,swatch,parent from image_links where status =%s LIMIT 1 FOR UPDATE",("fetched",))
parent = cur.fetchall()
for row in parent:
mylistitems = row[0].split(",")
swatches = row[2].split(",")
myurlsitems = row[1].split(",")
pid = row[3]
if asinlist != ['']:
merged = tuple(zip(mylistitems ,myurlsitems ,swatches))
return render_template('home.html',firstimage= myurlsitems[0],merged=merged)
else:
cur.execute("UPDATE asin_links SET status = %s WHERE pid= %s", ("invalid",pid,))
conn.commit()
return redirect(url_for('index'))
I can't see any "current user" specific parameters used in your sql query or any data filtering decided on some user ID.
Basically, if you are running the same code, same query for all requests on this endpoint, it will never be really unique. You need to add some user specific checks so you can differentiate the output for the current requesting user.
Depending on your use-case and database models, if the data in the table image_links is also created/inserted by some user action you might want additionally save some user ID alongside these values, eg. by extending the table model with another "user_id" column and on insert also add the id of the current user.
You are using some auth decorator #is_logged_in, if you are already handling users in some table then the another user_id column could be a reference to the respective user's primary key. Then, in your example, you would just add additional where user_id = check with the current user's primary key.
As I see in this SQL query:
SELECT mylist, myurl, swatch, parent FROM image_links WHERE status
perhaps you did specify the related user to get its own specific data, try to replace that last "where" with:
WHERE id = (user.id) --> user object
or you could use the AND keyword, something like
WHERE status = (x) AND id = (y)

inserting data into multiple mySQL tables using flask with one query

I have two distinct tables in mySQL :
'Books' ('id', 'title', 'author_id')
and
'Authors' ('id', 'author')
Both id's are auto-increment and the tables have a one to many relationship with the foreign key ('author_id') on Books. My task is to enter a new author and book in one single swoop since data are coming via a POST method to these tables from the same form in HTML.
I have manually tried this on mySQL and it works great:
INSERT INTO authors (author, created_at, updated_at)
VALUES ('Gerald Durrell',NOW(),NOW());
INSERT INTO books (title, rating, created_at, updated_at, author_id)
VALUES ('Birds',5, NOW(),NOW(), LAST_INSERT_ID())
In my Flask app, I have the exact same query but the system gets mad and doesn't allow me to do it.
My models.py
mysql = connectToMySQL('books')
query = 'INSERT INTO authors (author, created_at, updated_at)
VALUES (%(author)s,NOW(),NOW()); INSERT INTO books
(title, created_at, updated_at, author_id) VALUES (% .
(title)s, NOW(),NOW(), LAST_INSERT_ID());'
data = {
'author': request.form['author'],
'title': request.form['title'],
}
mysql.query_db(query,data)
my html:
<form action='/addbook' method='POST'>
<label for='title'>Book Title:</label>
<input type="text" name='title'>
<p>Enter new author:</p>
<input name='author' type="text">
<input type='submit' value='Click to add book'>
</form>
The command works manually when I enter it in mySQL. But it crashes in Flask. I do know that the connection between mySQL and Flask app is good because I successfully entered users who have navigated to this 'Add book page'.
This is the exact error message that pops up in my terminal:
Something went wrong (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INSERT INTO books (title, rating, created_at, updated_at, author_id) VAL' at line 1")
The workaround is to incorporate author into the book table, but then I won't be able to iterate through authors in a different section of the app.
After a bit of struggle, it turns out that Flask does not do multiple queries. So I changed the program to have two different routes.
Route 1 : populate the author table with author fields.
and then return a the id-value which flask does automatically anyway and put it in session.
Then route 2: populate the book table with the same form fields and also the author_id field from session.

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+'%',))

Using foreign keys in sqlite3 for Python

I'm writing a program that creates a sqlite3 database through python. I have one table of Authors (AuthorID, Name) and a second table of books (BookID, Title, AuthorID) I've created these as shown below:
Authors = sqlite3.connect('Authors.db')
Authors.execute('''CREATE TABLE Authors
(AuthorID INT PRIMARY KEY,
Name TEXT);''')
Authors.close()
Books = sqlite3.connect('Books.db')
Books.execute('''CREATE TABLE Books
(BookID INT PRIMARY KEY,
Title TEXT,
AuthorID INT,
FOREIGN KEY(AuthorID) REFERENCES Authors(AuthorID));''')
Books.close()
I then go to add a record to each of the tables as shown below:
Authors = sqlite3.connect('Authors.db')
Authors.execute("INSERT INTO Authors (AuthorID, Name) \
VALUES (1, 'Jane Austin')");
Authors.commit()
Authors.close()
Books = sqlite3.connect('Books.db')
Books.execute("INSERT INTO Books (BookID, Title, AuthorID) \
VALUES (1, 'Emma', 1)");
Books.commit()
Books.close()
The database is correctly updated but I don't think the foreign keys are working correctly because it allows me to remove the Author 'Jane Austin', when there are books associated with it.
I've seen some tutorials use this line:
Books.execute("PRAGMA foreign_keys = 1")
Is this the answer to the problem and if so where do I put this line?
The PRAGMA foreign_keys setting applies to a connection, so you should execute it immediately after calling sqlite3.connect().
Please note that foreign key constraints work only inside the same database; you should put both tables into the same file.
So to do what you want to do you need to create one database file with 2 tables.
Example:
conn=sqlite3.connect("clientdatabase.db")
conn.execute("PRAGMA foreign_keys = 1")
cur=conn.cursor()
# Create 2 tables if they don't exist: Clients and Work_Done
cur.execute('''CREATE TABLE IF NOT EXISTS Clients
(CID INTEGER PRIMARY KEY,
First_Name TEXT NOT NULL,
Last_Name TEXT,
Business_Name TEXT,
Phone TEXT,
Address TEXT,
City TEXT,
Notes TEXT,
Active_Status TEXT NOT NULL)''')
cur.execute('''CREATE TABLE IF NOT EXISTS Work_Done
(ID INTEGER PRIMARY KEY,
Date TEXT NOT NULL,
Onsite_Contact TEXT,
Work_Done TEXT NOT NULL,
Parts_Installed TEXT,
Next_Steps TEXT,
CID INT,
FOREIGN KEY (CID) REFERENCES CLIENTS (CID))''')
conn.commit()
Note that both tables are in the same database and you add the line after connection and before the cursor object.
Hope this helps.
Also note that if there is an active transaction, the PRAGMA foreign_keys does not work. There is no error message if you try to do so but foreign keys will still be turned off.
If you have problems with foreign keys even after using the pragma, it may be worth an attempt to execute COMMIT once before using it.
FYI, according to the recent official document, you can use PRAGMA foreign_keys = ON.
connection = sqlite3.connect(DB_FILE)
connection.execute('PRAGMA foreign_keys = ON')
cursor = connection.cursor()
(...)

Categories

Resources