From c4fe3422a3cc4ec343d23e8c99457d47b202c400 Mon Sep 17 00:00:00 2001 From: Damien De Paoli Date: Sun, 8 Nov 2020 15:07:36 +1100 Subject: [PATCH] Keeping flask-marshmallow as its too hard to do my own objects, due to SqlAlchemy using its own list that is not iterable, etc. Added Genre, ALSO, beware table names with an underscore are messed with, and should be explictly defined - found out this the hard way with genre_lst --- main.py | 43 +++++++++++++++++++++++++++++++------------ templates/books.html | 1 + 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/main.py b/main.py index a4fefdf..192cd02 100644 --- a/main.py +++ b/main.py @@ -22,6 +22,11 @@ book_publisher_link = db.Table('book_publisher_link', db.Model.metadata, db.Column('publisher_id', db.Integer, db.ForeignKey('publisher.id')) ) +book_genre_link = db.Table('book_genre_link', db.Model.metadata, + db.Column('book_id', db.Integer, db.ForeignKey('book.id')), + db.Column('genre_id', db.Integer, db.ForeignKey('genre_lst.id')) +) + class Book(db.Model): id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True) title = db.Column(db.String(100), unique=True, nullable=False) @@ -37,26 +42,33 @@ class Book(db.Model): author = db.relationship('Author', secondary=book_author_link) publisher = db.relationship('Publisher', secondary=book_publisher_link) + genre = db.relationship('Genre_Lst', secondary=book_genre_link ) def __repr__(self): - return "".format(self.title, self.id, self.year_published, self.rating, self.condition, self.owned, self.covertype, self.notes, self.blurb, self.created, self.modified, self.publisher ) + return "".format(self.id, self.author, self.title, self.year_published, self.rating, self.condition, self.owned, self.covertype, self.notes, self.blurb, self.created, self.modified, self.publisher ) class Author(db.Model): id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True) firstnames = db.Column(db.String(50), unique=False, nullable=False) surname = db.Column(db.String(30), unique=False, nullable=False) - book = db.relationship('Book', secondary=book_author_link ) - def __repr__(self): - return "".format(self.firstnames, self.surname, self.id) + return "".format(self.id,self.firstnames, self.surname) class Publisher(db.Model): id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True) name = db.Column(db.String(50), unique=False, nullable=False) def __repr__(self): - return "".format(self.name, self.id) + return "".format(self.id, self.name) + +class Genre_Lst(db.Model): + __tablename__ = "genre_lst" + id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True) + genre = db.Column(db.String(20), unique=False, nullable=False) + + def __repr__(self): + return "".format(self.id, self.genre) ### setup serializer schemas, to make returning books/authors easier class AuthorSchema(ma.SQLAlchemyAutoSchema): @@ -71,16 +83,24 @@ class PublisherSchema(ma.SQLAlchemyAutoSchema): include_relationships = True load_instance = True +class Genre_LstSchema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Genre_Lst + include_relationships = True + load_instance = True + class BookSchema(ma.SQLAlchemyAutoSchema): author = ma.Nested(AuthorSchema, many=True) - publisher = ma.Nested(PublisherSchema, many=True) + publisher = ma.Nested(PublisherSchema) class Meta: model = Book include_relationships = True load_instance = True -author_schema = AuthorSchema() +### DDP: do I need many=True on Author as books have many authors? (or in BookSchema declaration above?) +author_schema = AuthorSchema(many=True) publisher_schema = PublisherSchema() +genre_schema = Genre_LstSchema(many=True) book_schema = BookSchema() ####################################### ROUTES ####################################### @@ -90,8 +110,8 @@ def books(): print(request.form) books = Book.query.all() - # want to get sub book info and patch it into the books object to at least reference sub_book_num and parent_book, - # then per book in jinja2, slide it into the right aprt of the table with the right markup to show its a sub book + # want to get sub book info and patch it into the books object to at least reference sub_book_num and parent_book, + # then per book in jinja2, slide it into the right aprt of the table with the right markup to show its a sub book subs = db.engine.execute ( "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) @@ -105,7 +125,7 @@ def book(id): book = Book.query.get(id) book_s = book_schema.dump(book) - # force sub books for jinja2 to be able to use + # force sub books for jinja2 to be able to use subs = db.engine.execute ( "select bsb.book_id, bsb.sub_book_id, bsb.sub_book_num, book.title, book.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 where bsb.book_id = {} and book.id = bsb.sub_book_id and book.id = bal.book_id and bal.author_id = author.id".format( id ) ) sub_book=[] for row in subs: @@ -118,9 +138,8 @@ def book(id): sub_book.append( { 'sub_book_id': row.sub_book_id, 'sub_book_num': row.sub_book_num, 'title' : row.title, 'rating': row.rating, 'year_published' : row.year_published, 'notes' : row.notes, 'author_id' : row.author_id, 'author' : row.author, 'genres' : tmp_g } ) book_s['sub_book'] = sub_book - print( book_s ) - return render_template("books.html", books=book_s ) + return render_template("books.html", books=book_s, subs=sub_book ) @app.route("/authors", methods=["GET"]) def author(): diff --git a/templates/books.html b/templates/books.html index e1d4af3..e166e61 100644 --- a/templates/books.html +++ b/templates/books.html @@ -73,6 +73,7 @@ + {{books.genre}} {% if books.sub_book is defined %}

sub_book is defined: {{books.sub_book}}

{% endif %}