fixed bug where when you remove a sub_book it left a whole in sub_book_num's, and rewrote to new sqlalchemy 2, all the direct sqls

This commit is contained in:
2023-06-11 11:23:48 +10:00
parent 4223b81641
commit 196f758372
3 changed files with 50 additions and 21 deletions

View File

@@ -90,9 +90,10 @@ def loan(id):
loan = Loan.query.get(id)
try:
if 'delete' in request.form:
st.SetMessage( f"Successfully deleted (id={loan.id}, who={loan.firsnames} {loan.surname})" )
st.SetMessage( f"Successfully deleted (id={loan.id}, who={loan.firstnames} {loan.surname})" )
# fall back to direct sql because loan.py is imported before Book_Loan_Link exists
db.engine.execute( f"delete from book_loan_link where loan_id = {loan.id}" )
with db.engine.connect() as conn:
conn.exec_driver_sql( f"delete from book_loan_link where loan_id = {loan.id}" )
loan = Loan.query.filter(Loan.id==id).delete()
if 'submit' in request.form:
st.SetMessage( f"Successfully Updated Loan (id={id})" )

60
main.py
View File

@@ -246,7 +246,8 @@ def GetBookIdFromBookSubBookLinkByIdAndSubBookNum( book_id, sub_book_num ):
# Just select sub_book data and hand add it to the books object, and use it in jinja2 to indent/order the books/sub books
# This data is used to sort/indent subbooks
def AddSubs(books):
subs = db.engine.execute ( "select * from book_sub_book_link" )
with db.engine.connect() as conn:
subs = conn.exec_driver_sql( "select * from book_sub_book_link" )
for row in subs:
index = next((i for i, item in enumerate(books) if item.id == row.sub_book_id), -1)
if index == -1:
@@ -257,7 +258,8 @@ def AddSubs(books):
# HACK: Couldn't work out ORM to excluded sub_book self-ref, so using basic python
# loop to remove sub_books from list
def RemSubs(books):
subs = db.engine.execute ( "select * from book_sub_book_link" )
with db.engine.connect() as conn:
subs = conn.exec_driver_sql( "select * from book_sub_book_link" )
for row in subs:
for i, item in enumerate(books):
if item.id == row.sub_book_id:
@@ -455,7 +457,8 @@ def subbooks_for_book(id):
####################################
# force sub books for jinja2 to be able to use (ORM is not giving all the details
####################################
subs = db.engine.execute ( "select bsb.book_id, bsb.sub_book_id, bsb.sub_book_num, book.title, \
with db.engine.connect() as conn:
subs = conn.exec_driver_sql( "select bsb.book_id, bsb.sub_book_id, bsb.sub_book_num, book.title, \
r.name as rating, book.year_published, book.notes, \
bal.author_id as author_id, author.surname||', '||author.firstnames as author \
from book_sub_book_link bsb, book, book_author_link bal, author, rating r\
@@ -471,14 +474,27 @@ def subbooks_for_book(id):
return render_template("subbooks_for_book.html", sub_books=sub_book, s2=subs )
################################################################################
# /remove_sub_book -> POST -> removes this subbook from parent
# /remove_subbook -> POST -> removes this subbook from parent, takes you back to
# /books (or /book/<parent_id> -- if you added a sub-book of parent_id
################################################################################
@app.route("/remove_subbook", methods=["POST"])
@login_required
def remove_sub_book():
parent_book_id=request.form['rem_sub_parent_id']
sub_book_id=request.form['rem_sub_sub_book_id']
sub_book=Book.query.get( sub_book_id )
remember=Book_Sub_Book_Link.query.filter(Book_Sub_Book_Link.book_id==parent_book_id, Book_Sub_Book_Link.sub_book_id==sub_book_id ).one()
orig_sub_book_num=remember.sub_book_num
try:
db.engine.execute("delete from book_sub_book_link where book_id = {} and sub_book_id = {}".format( request.form['rem_sub_parent_id'], request.form['rem_sub_sub_book_id']) )
# delete book-subbook link for this subbook
db.session.delete(remember)
# need to reorder old sub_book_nums to remove the new gap we created
bsbls=Book_Sub_Book_Link.query.filter(Book_Sub_Book_Link.book_id==parent_book_id, Book_Sub_Book_Link.sub_book_num>=orig_sub_book_num ).all()
for sb in bsbls:
sb.sub_book_num=sb.sub_book_num-1
# now remove subbook itself
db.session.delete(sub_book)
db.session.commit()
return redirect( '/book/{}'.format(request.form['rem_sub_parent_id']) )
except SQLAlchemyError as e:
@@ -530,13 +546,15 @@ def new_book():
db.session.commit()
# this is a sub-book we have added
if 'parent_id' in request.form:
db.engine.execute( "insert into book_sub_book_link ( book_id, sub_book_id, sub_book_num ) values ( {}, {}, (select COALESCE(MAX(sub_book_num),0)+1 from book_sub_book_link where book_id = {}) )".format( request.form['parent_id'], book.id, request.form['parent_id'] ) )
with db.engine.connect() as conn:
conn.exec_driver_sql( "insert into book_sub_book_link ( book_id, sub_book_id, sub_book_num ) values ( {}, {}, (select COALESCE(MAX(sub_book_num),0)+1 from book_sub_book_link where book_id = {}) )".format( request.form['parent_id'], book.id, request.form['parent_id'] ) )
parent=Book.query.get(request.form['parent_id'])
if len(parent.series) > 0:
# we have added a sub-book to something in a series
# already, so add a bsl for the next book_num
for s in parent.bsl:
db.engine.execute( "insert into book_series_link ( series_id, book_id, book_num ) values ( {}, {}, (select COALESCE(MAX(book_num),0)+1 from book_series_link where series_id={}) )".format( s.series_id, book.id, s.series_id ) )
with db.engine.connect() as conn:
conn.exec_driver_sql( "insert into book_series_link ( series_id, book_id, book_num ) values ( {}, {}, (select COALESCE(MAX(book_num),0)+1 from book_series_link where series_id={}) )".format( s.series_id, book.id, s.series_id ) )
db.session.commit()
st.SetMessage( "Created new Book ({})".format(book.title) )
cnt=1
@@ -544,7 +562,8 @@ def new_book():
if 'bsl-book_id-' in field and field != 'bsl-book_id-NUM':
cnt=int(re.findall( '\d+', field )[0])
sql="insert into book_series_link (book_id, series_id, book_num) values ( {}, {}, {} )".format( book.id, request.form['bsl-series_id-{}'.format(cnt)], request.form['bsl-book_num-{}'.format(cnt)])
db.engine.execute( sql )
with db.engine.connect() as conn:
conn.exec_driver_sql( sql )
cnt=cnt+1
return redirect( '/book/{}'.format(book.id) )
else:
@@ -660,7 +679,8 @@ def book(id):
CheckSeriesChange={'type':'child', 'pid': book.parent[0].id, 'bid': book.id, 'removing_series': removing_series }
else:
# delete all bsls
db.engine.execute("delete from book_series_link where book_id = {}".format( book.id ) )
with db.engine.connect() as conn:
conn.exec_driver_sql( "delete from book_series_link where book_id = {}".format( book.id ) )
cnt=1
for field in request.form:
@@ -670,7 +690,8 @@ def book(id):
sql="insert into book_series_link (book_id, series_id) values ( {}, {} )".format( request.form['bsl-book_id-{}'.format(cnt)], request.form['bsl-series_id-{}'.format(cnt)] )
else:
sql="insert into book_series_link (book_id, series_id, book_num) values ( {}, {}, {} )".format( request.form['bsl-book_id-{}'.format(cnt)], request.form['bsl-series_id-{}'.format(cnt)], request.form['bsl-book_num-{}'.format(cnt)])
db.engine.execute( sql )
with db.engine.connect() as conn:
conn.exec_driver_sql( sql )
db.session.commit()
# reset rating on this series as the book has changed (and maybe the rating has changed)
for field in request.form:
@@ -705,11 +726,12 @@ def book(id):
def GetCount( what, where ):
st="select count(id) as count from book where "
res=db.engine.execute( st + where )
with db.engine.connect() as conn:
res = conn.exec_driver_sql( st+where )
rtn={}
for row in res:
rtn['stat']=what
rtn['value']=row['count']
rtn['value']=row.count
return rtn
@app.route("/stats", methods=["GET"])
@@ -737,7 +759,8 @@ def rem_books_from_loan(id):
for field in request.form:
rem_id=int(re.findall( '\d+', field )[0])
try:
db.engine.execute("delete from book_loan_link where book_id = {} and loan_id = {}".format( rem_id, id ))
with db.engine.connect() as conn:
conn.exec_driver_sql( "delete from book_loan_link where book_id = {} and loan_id = {}".format( rem_id, id ))
db.session.commit()
except SQLAlchemyError as e:
st.SetAlert("danger")
@@ -750,7 +773,8 @@ def add_books_to_loan(id):
for field in request.form:
add_id=int(re.findall( '\d+', field )[0])
try:
db.engine.execute("insert into book_loan_link (book_id, loan_id) values ( {}, {} )".format( add_id, id ))
with db.engine.connect() as conn:
conn.exec_driver_sql( "insert into book_loan_link (book_id, loan_id) values ( {}, {} )".format( add_id, id ))
db.session.commit()
except SQLAlchemyError as e:
st.SetAlert("danger")
@@ -762,8 +786,9 @@ def add_books_to_loan(id):
def rem_parent_books_from_series(pid):
print ("pid={}".format(pid) )
try:
db.engine.execute("delete from book_series_link where book_id in ( select sub_book_id from book_sub_book_link where book_id = {} ) ".format( pid ))
db.engine.execute("delete from book_series_link where book_id = {}".format( pid ))
with db.engine.connect() as conn:
conn.exec_driver_sql( "delete from book_series_link where book_id in ( select sub_book_id from book_sub_book_link where book_id = {} ) ".format( pid ))
conn.exec_driver_sql( "delete from book_series_link where book_id = {}".format( pid ))
db.session.commit()
except SQLAlchemyError as e:
st.SetAlert("danger")
@@ -825,7 +850,8 @@ def unrated_books():
return render_template("books.html", books=books, page_title="Books with no rating", show_cols='Rating', hide_cols='' )
def FindMissingBooks():
tmp = db.engine.execute("select s.*, count(bsl.book_num) from book_series_link bsl, series s where bsl.book_num is not null and s.id = bsl.series_id group by s.id order by s.title")
with db.engine.connect() as conn:
tmp=conn.exec_driver_sql( "select s.*, count(bsl.book_num) from book_series_link bsl, series s where bsl.book_num is not null and s.id = bsl.series_id group by s.id order by s.title")
books=[]
sold=Owned.query.filter(Owned.name=='Sold').all()
for t in tmp:

View File

@@ -41,13 +41,15 @@ class SeriesForm(FlaskForm):
delete = SubmitField('Delete' )
def CalcAvgRating(sid):
res=db.engine.execute( f"select round(avg(to_number(r.name, '99')),1) as rating from book b, rating r, series s, book_series_link bsl where s.id={sid} and s.id = bsl.series_id and bsl.book_id = b.id and b.rating = r.id and r.name ~ E'^\\\\d+$'" )
with db.engine.connect() as conn:
res=conn.exec_driver_sql( f"select round(avg(to_number(r.name, '99')),1) as rating from book b, rating r, series s, book_series_link bsl where s.id={sid} and s.id = bsl.series_id and bsl.book_id = b.id and b.rating = r.id and r.name ~ E'^\\\\d+$'" )
for row in res:
rating = row.rating
return rating
def ListOfSeriesWithMissingBooks():
res=db.engine.execute("select id, title, num_books, count from ( select s.id, s.title, s.num_books, count(bsl.book_id) from series s, book_series_link bsl where s.id = bsl.series_id group by s.id ) as foo where num_books > count")
with db.engine.connect() as conn:
res=conn.exec_driver_sql( "select id, title, num_books, count from ( select s.id, s.title, s.num_books, count(bsl.book_id) from series s, book_series_link bsl where s.id = bsl.series_id group by s.id ) as foo where num_books > count")
tmp=[]
for row in res:
tmp.append({'id': row[0], 'title': row[1]})