17、flask-圖書簡單館專案

little小新發表於2024-07-28

為了掌握模型可以練一下、以下是程式碼:

app.py

from App import create_app

app = create_app()

if __name__ == '__main__':
    app.run(debug=True)

views.py

from flask import Blueprint, render_template
from datetime import datetime
from .models import *

#建立藍圖(路由)
blue = Blueprint('book', __name__)  # 建立藍圖 ,book:藍圖名稱,__name__:當前模組名稱

"""
實現功能:
1、在書籍的 book_index.html中有一個檢視全部書籍的超連結按鈕,點選進入書籍列表book_list.html頁面
2、在書籍的 book_list.html中有一個顯示所有書籍名稱的按鈕,點選書名可以進入書籍詳情book_detail.html頁面
3、在書籍的 book_detail.html中有一個點選檢視書籍的作者和出版社,進入作者詳情的author_detail.html和出版社詳情的publisher_detail.html頁面

"""

@blue.route('/')


# 書籍首頁
@blue.route('/')
@blue.route('/bookindex/')
def book_index():
    return render_template('book_index.html')


# 書籍列表
@blue.route('/booklist/')
def book_list():
    books = Book.query.all()    # 查詢所有書籍
    return render_template('book_list.html', books=books)

# 書籍詳情
@blue.route('/bookdetail/<int:bookid>')
def book_detail(bookid):
    book = Book.query.get(bookid)
    return render_template('book_detail.html', book=book)

# 作者詳情
@blue.route('/authordetail/<int:authorid>')
def author_detail(authorid):
    author = Author.query.get(authorid)
    return render_template('author_detail.html', author=author)


# 出版社詳情
@blue.route('/publisherdetail/<int:publisherid>')
def publisher_detail(publisherid):
    publisher = Publisher.query.get(publisherid)
    return render_template('publisher_detail.html', publisher=publisher)

models.py

from .exts import db    #匯入db物件

"""
作者 : 書籍 => 1:n  (一本書有一個作者完成,一個作者可以創作多本書)
出本社:書籍  => n:n  (一個出版社可以出版多本書,一本書可以有多個出版社出版)
"""


#作者
class Author(db.Model):
    __tablename__ = 'author'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), unique=True)
    age = db.Column(db.Integer, default=1)
    sex = db.Column(db.Boolean, default=True)
    email = db.Column(db.String(200))

    # 關聯關係
    # backref:反向引用,author:表示在Book表中的外來鍵欄位名
    # 這個book的作用是:當例項化Author物件後、可以使用物件.book.all()獲取所有書籍資訊或物件.book.title獲取書籍標題
    book = db.relationship('Book', backref='author', lazy='dynamic')

# 書籍
class Book(db.Model):
    __tablename__ = 'book'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(50), unique=True)
    ##這裡注意、資料遷移後、如果手動插入資料,有時會被識別成時間戳、從而導致獲取報錯:TypeError: fromisoformat: argument must be str
    # 所以建議手動插入資料時使用sql命令插入()或ORM語句插入
    # 或者先插入時間戳再使用sql語句修改:UPDATE book SET date = '2021-01-01 12:00:00.000' WHERE id = 3
    date = db.Column(db.DateTime)

    # 1對多(作者 - 書籍) ,外來鍵
    # 透過作者id,關聯到作者表
    author_id = db.Column(db.Integer, db.ForeignKey(Author.id))

# 中間表(書籍-出版社)
book_publisher = db.Table(
    'book_publisher',   #表名
    # 透過書籍id,關聯到書籍表
    db.Column('book_id', db.Integer, db.ForeignKey('book.id'), primary_key=True),   # 外來鍵,

    # 透過出版社id,關聯到出版社表
    db.Column('publisher_id', db.Integer, db.ForeignKey('publisher.id'), primary_key=True)  # 外來鍵
)

# 出版社
class Publisher(db.Model):
    __tablename__ = 'publisher'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), unique=True)
    address = db.Column(db.String(200))
    city = db.Column(db.String(100))
    province = db.Column(db.String(100))
    country = db.Column(db.String(100))
    website = db.Column(db.String(200))

    # 多對多,關聯book表
    # Book: 表示關聯的表(這裡是Book類)
    # backref: 反向引用、publisher:表示在Book表中的外來鍵欄位名
    # lazy:延遲載入
    # secondary:繫結中間表
    # 透過關聯到書籍Book表,獲取書籍資訊
    # # 這個books的作用是:當例項化Author物件後、可以使用物件.book.all()獲取所有書籍資訊或物件.book.title獲取書籍標題
    books = db.relationship('Book', backref='publishers', secondary=book_publisher, lazy='dynamic')

exts.py

from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

#初始化外掛
db = SQLAlchemy()
migrate = Migrate()

#和app物件繫結
def init_exts(app):
    db.init_app(app)
    migrate.init_app(app,db)

__init__.py

from flask import Flask
from .views import blue
from .exts import init_exts


def create_app():
    app = Flask(__name__)   # 建立flask應用

    #註冊藍圖
    app.register_blueprint(blueprint=blue)

    #配置資料庫
    db_uri = 'sqlite:///sqlite3.db'     #sqlite的配置
    # db_uri = 'mysql+pymysql://root:123456@127.0.0.1:3306/flask_db?charset=utf8mb4'  #mysql的配置
    app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    #初始化外掛
    init_exts(app=app)

    return app

book_index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>書籍首頁</title>
</head>
<body>

    <h2>書籍首頁</h2>
    <hr>

    <a href="/booklist/">檢視所有書籍</a>

</body>
</html>

book_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>書籍列表</title>
</head>
<body>

    <h2>書籍列表</h2>
    <hr>

    <ul>
        {% for book in books %}
            <li>
                <a href="/bookdetail/{{ book.id }}">{{ book.title }}</a>
                {# 或使用:url_for('藍圖名.檢視函式名', 屬性名(自定義)=屬性值) #}
                {# <a href="{{ url_for('book.book_detail', bookid=book.id) }}">{{ book.title }}</a>#}
            </li>
        {% endfor %}

    </ul>


</body>
</html>

book_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>書籍詳情</title>
</head>
<body>
    <h2>書籍詳情</h2>
    <hr>

    <p>書籍標題:{{ book.title }}</p>
    <p>書籍出版時間:{{ book.date }}</p>
    <p>作者:
        <a href="/authordetail/{{ book.author.id }}">{{ book.author.name }}</a>
    </p>

    <p>出版社:
        {% for publisher in book.publishers %}
            <a href="/publisherdetail/{{ publisher.id }}">{{ publisher.name }}</a>
            {% if not loop.last %} | {% endif %}    {# 如果不是最後一個元素,就新增 | #}
        {% endfor %}
    </p>

</body>
</html>

author_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>作者詳情</title>
</head>
<body>
    <h2>作者詳情</h2>
    <hr>

    <p>
        作者:{{ author.name }}
    </p>
    <p>作者年齡:{{ author.age }}</p>
    <p>作者性別:{{ author.sex }}</p>
    <p>作者郵箱:{{ author.email }}</p>

    <p>我的作品:
        {#  這裡透過models.py中作者模型的關聯關係的book屬性,獲取作者的所有作品  #}
        {% for book in author.book %}
            <a href="/bookdetail/{{ book.id }}">{{ book.title }}</a>
            {% if not loop.last %} | {% endif %}    {# 如果不是最後一個元素,就新增 | #}
        {% endfor %}

    </p>
</body>
</html>

publisher_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>出版社詳情</title>
</head>
<body>
    <h2>出版社詳情</h2>
    <hr>

    <p>出版社名稱:{{ publisher.name }}</p>
    <p>出版社地址:{{ publisher.address }}</p>
    <p>出版社城市:{{ publisher.city }}</p>
    <p>出版社省份:{{ publisher.province }}</p>
    <p>出版社國家:{{ publisher.country }}</p>
    <p>出版社的網站:{{ publisher.website }}</p>

    <p>出版社的出版書籍:
        {#  這裡透過models.py中出版社模型的關聯關係的books屬性,獲取所有書籍  #}
        {% for book in publisher.books %}
            <a href="/bookdetail/{{ book.id }}">{{ book.title }}</a>
            {% if not loop.last %} | {% endif %}    {# 如果不是最後一個元素,就新增 | #}
            {% endif %}
        {% endfor %}

    </p>

</body>
</html>

專案目錄結構:

效果:

相關文章