remove .format() and get all updates to have crrect content

This commit is contained in:
2022-07-03 20:38:33 +10:00
parent 8834893df3
commit 021bf91e16
12 changed files with 81 additions and 59 deletions

13
BUGs
View File

@@ -1,3 +1,16 @@
### fix to get this working with bs 5...
editing a book needs to use input groups
+ buttons (add/rem say authors) is in wrong spot
- buttons at bottom are broken still
edit series needs input groups
sub-books table looks off (notes/etc. not stretching full width)
even navbar is not inset from left-margin (see pa-dev)
get rid of font-awesome and use bootstrap5 icons
sort through dataTables calls in books_for_series.html (ever called without base?) -- Maybe as part of an ajax call?
upgrade bootstrap, dataTables, etc.
#### BUGS (next-20)
### DB/back-end

View File

@@ -1,4 +1,4 @@
FROM ubuntu:20.04
FROM ubuntu:22.04
WORKDIR /code
USER root
ENV PJM_UID=500

9
README
View File

@@ -28,6 +28,15 @@ sudo docker-compose -f /srv/docker/config/docker-compose.yml up bookdb_web
########################################################## Remember:
MUST use form.errors when we have a validator that is fancier than not empty (year_published in book and num_books in series SO FAR)
##### make backup / export:
ddp@mara:/srv/docker/container/bookdb_dev$ sudo docker exec -it bookdb_dev bash
root@5eff50ab6cdc:/# pg_dump --user=ddp library > /docker-entrypoint-initdb.d/tables.sql
#### if we want to upgrade postgres, do this extra step
sudo docker-compose -f /srv/docker/config/docker-compose.yml stop bookdb_dev
sudo rm -rf /srv/docker/container/bookdb_dev/data
#tweak docker-compose.yml to upgrade PG...
sudo docker-compose -f /srv/docker/config/docker-compose.yml up -d bookdb_dev
########################################################### TODOS (next 29):
Validation:

View File

@@ -16,7 +16,7 @@ class Author(db.Model):
firstnames = db.Column(db.String(50), unique=False, nullable=False)
def __repr__(self):
return "<id: {}, firstnames: {}, surname: {}>".format(self.id,self.firstnames, self.surname)
return f"<id: {self.id}, firstnames: {self.firstnames}, surname: {self.surname}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Author into json / useful in jinja2
@@ -63,11 +63,11 @@ def new_author():
try:
db.session.add(author)
db.session.commit()
st.SetMessage( "Created new Author ({})".format(author) )
st.SetMessage( f"Created new Author ({author.surname}, {author.firstnames})" )
return redirect( '/authors' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add Author:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add Author:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
################################################################################
@@ -83,18 +83,18 @@ def author(id):
try:
author = Author.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted Author: ({})".format( author ) )
st.SetMessage( f"Successfully deleted Author: ({author.surname}, {author.firstnames})" )
author = Author.query.filter(Author.id==id).delete()
if 'submit' in request.form:
st.SetMessage("Successfully Updated Author: (From: {}".format(author) )
st.SetMessage( f"Successfully Updated Author: (From: {author.surname}, {author.firstnames}" )
author.surname = request.form['surname']
author.firstnames = request.form['firstnames']
st.AppendMessage(" To: {}".format(author) )
st.AppendMessage( f" To: {author.surname}, {author.firstnames})" )
db.session.commit()
return redirect( '/authors' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Author:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Author:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
author = Author.query.get(id)

View File

@@ -15,7 +15,7 @@ class Condition(db.Model):
name = db.Column(db.String(50), unique=True, nullable=False)
def __repr__(self):
return "<id: {}, name: {}>".format(self.id,self.name)
return f"<id: {self.id}, name: {self.name}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Condition into json / useful in jinja2
@@ -58,11 +58,11 @@ def new_condition():
try:
db.session.add(condition)
db.session.commit()
st.SetMessage( "Created new Condition (id={})".format(condition.id) )
st.SetMessage( f"Created new Condition (id={condition.id})" )
return redirect( '/conditions' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add condition:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add condition:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
################################################################################
@@ -78,16 +78,16 @@ def condition(id):
try:
condition = Condition.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, name={})".format( condition.id, condition.name ) )
st.SetMessage(f"Successfully deleted (id={condition.id}, name={condition.name})" )
condition = Condition.query.filter(Condition.id==id).delete()
if 'submit' in request.form:
st.SetMessage("Successfully Updated Condition (id={})".format(id) )
st.SetMessage( f"Successfully Updated Condition (id={id})" )
condition.name = request.form['name']
db.session.commit()
return redirect( '/conditions' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Condition:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Condition:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
condition = Condition.query.get(id)

View File

@@ -15,7 +15,7 @@ class Covertype(db.Model):
name = db.Column(db.String(50), unique=True, nullable=False)
def __repr__(self):
return "<id: {}, name: {}>".format(self.id,self.name)
return f"<id: {self.id}, name: {self.name}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Covertype into json / useful in jinja2
@@ -58,11 +58,11 @@ def new_covertype():
try:
db.session.add(covertype)
db.session.commit()
st.SetMessage( "Created new Covertype (id={})".format(covertype.id) )
st.SetMessage( f"Created new Covertype (id={covertype.id})" )
return redirect( '/covertypes' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add covertype:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add covertype:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
@@ -79,16 +79,16 @@ def covertype(id):
try:
covertype = Covertype.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, name={})".format( covertype.id, covertype.name ) )
st.SetMessage( f"Successfully deleted (id={covertype.id}, name={covertype.name})" )
covertype = Covertype.query.filter(Covertype.id==id).delete()
if 'submit' in request.form:
st.SetMessage("Successfully Updated Covertype (id={})".format(id) )
st.SetMessage( f"Successfully Updated Covertype (id={id})" )
covertype.name = request.form['name']
db.session.commit()
return redirect( '/covertypes' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Covertype:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Covertype:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
covertype = Covertype.query.get(id)

View File

@@ -15,7 +15,7 @@ class Genre(db.Model):
name = db.Column(db.String(50), unique=True, nullable=False)
def __repr__(self):
return "<id: {}, name: {}>".format(self.id,self.name)
return f"<id: {self.id}, name: {self.name}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Genre into json / useful in jinja2
@@ -58,11 +58,11 @@ def new_genre():
try:
db.session.add(genre)
db.session.commit()
st.SetMessage( "Created new Genre (id={})".format(genre.id) )
st.SetMessage( f"Created new Genre (id={genre.id})" )
return redirect( '/genres' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add Genre:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add Genre:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
################################################################################
@@ -78,16 +78,16 @@ def genre(id):
try:
genre = Genre.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, name={})".format( genre.id, genre.name ) )
st.SetMessage( f"Successfully deleted (id={genre.id}, name={genre.name})" )
genre = Genre.query.filter(Genre.id==id).delete()
if 'submit' in request.form:
st.SetMessage("Successfully Updated Genre (id={})".format(id) )
st.SetMessage( f"Successfully Updated Genre (id={id})" )
genre.name = request.form['name']
db.session.commit()
return redirect( '/genres' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Genre:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Genre:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
genre = Genre.query.get(id)

14
loan.py
View File

@@ -20,7 +20,7 @@ class Loan(db.Model):
date_lent = db.Column(db.Date, nullable=False )
def __repr__(self):
return "<id: {}, firstnames: {}, surname: {}>".format(self.id,self.firstnames, self.surname)
return f"<id: {self.id}, firstnames: {self.firstnames}, surname: {self.surname}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Loan into json / useful in jinja2
@@ -69,11 +69,11 @@ def new_loan():
try:
db.session.add(loan)
db.session.commit()
st.SetMessage( "Created new Loan (id={})".format(loan.id) )
st.SetMessage( f"Created new Loan (id={loan.id})" )
return redirect( '/loans' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add Loan:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add Loan:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
@@ -90,12 +90,12 @@ def loan(id):
loan = Loan.query.get(id)
try:
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, who={} {})".format( loan.id, loan.firstnames, loan.surname ) )
st.SetMessage( f"Successfully deleted (id={loan.id}, who={loan.firsnames} {loan.surname})" )
# fall back to direct sql because loan.py is imported before Book_Loan_Link exists
db.engine.execute("delete from book_loan_link where loan_id = {}".format( loan.id ))
db.engine.execute( 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("Successfully Updated Loan (id={})".format(id) )
st.SetMessage( f"Successfully Updated Loan (id={id})" )
loan.firstnames = request.form['firstnames']
loan.surname = request.form['surname']
loan.surname = request.form['surname']
@@ -105,7 +105,7 @@ def loan(id):
return redirect( '/loans' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Loan:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Loan:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
loan = Loan.query.get(id)

View File

@@ -15,7 +15,7 @@ class Owned(db.Model):
name = db.Column(db.String(50), unique=True, nullable=False)
def __repr__(self):
return "<id: {}, name: {}>".format(self.id,self.name)
return f"<id: {self.id}, name: {self.name}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Owned into json / useful in jinja2
@@ -58,11 +58,11 @@ def new_owned():
try:
db.session.add(owned)
db.session.commit()
st.SetMessage( "Created new Owned Type (id={})".format(owned.id) )
st.SetMessage( f"Created new Owned Type (id={owned.id})" )
return redirect( '/owneds' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add Ownership type:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add Ownership type:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
################################################################################
@@ -77,16 +77,16 @@ def owned(id):
try:
owned = Owned.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, name={})".format( owned.id, owned.name ) )
st.SetMessage( f"Successfully deleted (id={owned.id}, name={owned.name})" )
owned = Owned.query.filter(Owned.id==id).delete()
if 'submit' in request.form:
owned.name = request.form['name']
st.SetMessage("Successfully Updated Owned (id={})".format(id) )
st.SetMessage( f"Successfully Updated Owned (id={id})" )
db.session.commit()
return redirect( '/owneds' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Ownership Type:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Ownership Type:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title='Edit Ownership Type', alert=st.GetAlert(), message=st.GetMessage() )
else:
obj = Owned.query.get(id)

View File

@@ -15,7 +15,7 @@ class Publisher(db.Model):
name = db.Column(db.String(50), unique=True, nullable=False)
def __repr__(self):
return "<id: {}, name: {}>".format(self.id,self.name)
return f"<id: {self.id}, name: {self.name}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Publisher into json / useful in jinja2
@@ -58,11 +58,11 @@ def new_publisher():
try:
db.session.add(publisher)
db.session.commit()
st.SetMessage( "Created new Publisher (id={})".format(publisher.id) )
st.SetMessage( f"Created new Publisher (id={publisher.id})" )
return redirect( '/publishers' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add Publisher:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add Publisher:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
################################################################################
@@ -78,16 +78,16 @@ def publisher(id):
try:
publisher = Publisher.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, name={})".format( publisher.id, publisher.name ) )
st.SetMessage( f"Successfully deleted (id={publisher.id}, name={publisher.name})" )
publisher = Publisher.query.filter(Publisher.id==id).delete()
if 'submit' in request.form:
st.SetMessage("Successfully Updated Publisher (id={})".format(id) )
st.SetMessage( f"Successfully Updated Publisher (id={id})" )
publisher.name = request.form['name']
db.session.commit()
return redirect( '/publishers' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Publisher:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Publisher:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
publisher = Publisher.query.get(id)

View File

@@ -15,7 +15,7 @@ class Rating(db.Model):
name = db.Column(db.String(50), unique=True, nullable=False)
def __repr__(self):
return "<id: {}, name: {}>".format(self.id,self.name)
return f"<id: {self.id}, name: {self.name}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Rating into json / useful in jinja2
@@ -58,11 +58,11 @@ def new_rating():
try:
db.session.add(rating)
db.session.commit()
st.SetMessage( "Created new Rating (id={})".format(rating.id) )
st.SetMessage( f"Created new Rating (id={rating.id})" )
return redirect( '/ratings' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add rating:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add rating:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
################################################################################
@@ -78,16 +78,16 @@ def rating(id):
try:
rating = Rating.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, name={})".format( rating.id, rating.name ) )
st.SetMessage( f"Successfully deleted (id={rating.id}, name={rating.name})" )
rating = Rating.query.filter(Rating.id==id).delete()
if 'submit' in request.form:
st.SetMessage("Successfully Updated Rating (id={})".format(id) )
st.SetMessage( f"Successfully Updated Rating (id={id})" )
rating.name = request.form['name']
db.session.commit()
return redirect( '/ratings' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Rating:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Rating:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
rating = Rating.query.get(id)

View File

@@ -18,7 +18,7 @@ class Series(db.Model):
note = db.Column(db.Text)
def __repr__(self):
return "<id: {}, title: {}, num_books: {}, calcd_rating: {}, note: {}>".format(self.id, self.title, self.num_books, self.calcd_rating, self.note)
return f"<id: {self.id}, title: {self.title}, num_books: {self.num_books}, calcd_rating: {self.calcd_rating}, note: {self.note}>"
################################################################################
# Helper class that inherits a .dump() method to turn class Series into json / useful in jinja2
@@ -41,7 +41,7 @@ class SeriesForm(FlaskForm):
delete = SubmitField('Delete' )
def CalcAvgRating(sid):
res=db.engine.execute("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={} and s.id = bsl.series_id and bsl.book_id = b.id and b.rating = r.id and r.name ~ E'^\\\\d+$'".format(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+$'" )
for row in res:
rating = row.rating
return rating
@@ -79,11 +79,11 @@ def new_series():
try:
db.session.add(series)
db.session.commit()
st.SetMessage( "Created new Series (id={})".format(series.id) )
st.SetMessage( f"Created new Series (id={series.id})" )
return redirect( '/seriess' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to add Series:</b>&nbsp;{}".format( e.orig) )
st.SetMessage( f"<b>Failed to add Series:</b>&nbsp;{e.orig}" )
return render_template("series.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
################################################################################
@@ -99,10 +99,10 @@ def series(id):
try:
series = Series.query.get(id)
if 'delete' in request.form:
st.SetMessage("Successfully deleted (id={}, title={})".format( series.id, series.title ) )
st.SetMessage( f"Successfully deleted (id={series.id}, title={series.title})" )
series = Series.query.filter(Series.id==id).delete()
if 'submit' in request.form and form.validate():
st.SetMessage("Successfully Updated Series (id={})".format(id) )
st.SetMessage( f"Successfully Updated Series (id={id})" )
series.title = request.form['title']
series.num_books = request.form['num_books']
series.calcd_rating = CalcAvgRating(id)
@@ -110,7 +110,7 @@ def series(id):
else:
message="<b>Failed to update Series:</b>"
for field in form.errors:
message = "{}<br>{}={}".format( message, field, form.errors[field] )
message= f"{message}<br>{field}={form.errors[field]}"
st.SetAlert("danger")
st.SetMessage(message)
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
@@ -118,7 +118,7 @@ def series(id):
return redirect( '/seriess' )
except SQLAlchemyError as e:
st.SetAlert( "danger" )
st.SetMessage( "<b>Failed to modify Series:</b>&nbsp;{}".format(e.orig) )
st.SetMessage( f"<b>Failed to modify Series:</b>&nbsp;{e.orig}" )
return render_template("edit_id_name.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() )
else:
series = Series.query.get(id)