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?
Related
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()
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)
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()
(...)
I want to do a Django Python MySQL query with WHERE (in sql) being a link generated from a previous query.
Hereby I paste my actual code:
def population(request):
db = MySQLdb.connect(user='xxxx', db='xxxxdb', passwd='xxxxpwd', host='localhost')
cursor = db.cursor()
cursor.execute("SELECT last_name FROM a_population WHERE country='Denmark' ORDER BY last_name")
denominazione_comune = cursor.fetchall();
rows_count = cursor.rowcount
db.close()
counter = 0
return render_to_response('list_last_name.html', {'lastname': last_name}, context_instance=RequestContext(request))
So from this code I get an (un)ordered list of family names. By clicking one of these family names I would like to create another query with the family name clicked as a parameter but I don't have a clue of how to do that.
Thanks a million to whom will give me some input.
Using Python I try to access a view of a view:
import sqlite3
conn = sqlite3.connect("test.db")
mydb = conn.cursor()
mydb.execute("CREATE TABLE TestTbl (MRTarget_id int, Fullmodel text)")
mydb.execute("CREATE TABLE TestTbl2 (Other_id int, Othermodel text)")
mydb.execute("CREATE VIEW TestView AS SELECT m.ROWID, m.MRTarget_id, m.Fullmodel, t.Othermodel FROM TestTbl m, TestTbl2 t")
mydb.execute("CREATE VIEW TestView2 AS SELECT m.Fullmodel, m.Othermodel FROM TestView m")
mydb.close()
Attempting to create TestView2, I get an error:
sqlite3.OperationalError: no such column: m.Fullmodel
Above SQL statements work fine from SQLite prompt. The database contains views of views; could it be that it is not possible to access these using Python?
I've had the same problem - and I found a solution. I believe your problem is that in your initial view 'TestView', the attribute names are actually m.ROWID, m.Fullmodel etc instead of just ROWID, Fullmodel etc.
A casual look at the views through sqlite manager won't reveal the m. appended to the front of each field name. If you run the Pragma query PRAGMA table_info TestView, the attribute extensions will be revealed.
So, change your TestView creation query to
CREATE VIEW TestView AS
SELECT m.ROWID as ROWID, m.MRTarget_id as MRTarget_id,... etc
and your second Create View query should run successfully - at least it did in my application.
Your code works fine for me.
You could try committing between creating the first view and the second:
conn.commit()