2024年1月7日 星期日

Flask 簡單的CRUD 以及配置 SQLAlchemy

 

1.匯入套件

from flask import Flask, render_template, request, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField,SelectField
from wtforms.validators import DataRequired,URL
from flask_bootstrap import Bootstrap5
from flask_sqlalchemy import SQLAlchemy

2.建立Flask物件實例,__name__是當前執行的模組名稱,所以就可知道從哪個模組啟動應用程式

app = Flask(__name__)

3.設定Flask應用程式資料庫的URI配置,下面設定告訴 SQLAlcjemy使用SQLite作為資料庫

SQLite URI:

"sqlite:///<name of database>.db"

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///new-books-collection.db"

MySQL URI:

app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://user:password@localhost/dbname"

PostgreSQL URI:

app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://user:password@localhost/dbname"

Oracle URI:

app.config['SQLALCHEMY_DATABASE_URI'] = "oracle://user:password@localhost/dbname"

MS SQL Server URI:

app.config['SQLALCHEMY_DATABASE_URI'] = "mssql+pyodbc://user:password@server/database"

-----這些URI中, USER 是資料庫使用者名稱,password是密碼,localhost or server式資料庫伺服器位置,dbname or database 是資料庫名稱


4.建立SQLAlchemy的實例

db = SQLAlchemy()

5.將Flask應用程式實例與SQLAlchemy實例進行綁定,後續才能在Flask應用程式使用SQLAlchemy提供的資料庫功能

db.init_app(app)


上面這些程式碼的目的是建立一個 Flask 應用程式,設定使用 SQLite 資料庫,並使用 SQLAlchemy 來處理與資料庫相關的操作。在這個基礎上,你可以建立模型 (Models)、定義資料表結構,並進行資料庫操作,例如新增、查詢、更新、刪除等。


6.定義模型

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, unique=True, nullable=False)
    email = db.Column(db.String)
表名稱"user"將自動分配給模型的表。
class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True,autoincrement=True)
    title = db.Column(db.String(250), unique=True, nullable=False)
    author = db.Column(db.String(250), nullable=False)
    rating = db.Column(db.String(250), nullable=False)

7.建立表

with app.app_context():
    db.create_all()


除了這些事情之外,在使用任何新的資料庫技術時要弄清楚的最關鍵的事情是如何對資料記錄進行CRUD

創造_(C)

_(R)

更新_(U)

刪除_(D)

Create A New Record

NOTE: When creating new records, the primary key fields is optional. you can also write:

new_book = Book(title="Harry Potter", author="J. K. Rowling", rating=9.3)

the id field will be auto-generated.


Read All Records

To read all the records we first need to create a "query" to select things from the database. When we execute a query during a database session we get back the rows in the database (a Result object). We then use scalars() to get the individual elements rather than entire rows.

Read A Particular Record By Query

To get a single element we can use scalar() instead of scalars().

@app.route('/')
def home():
    #讀取db
    '''
    Book.query.order_by(Book.title).all()
    使用 SQLAlchemy 提供的 ORM (Object-Relational Mapping) 操作,這是更高層次的抽象,它將資料庫查詢轉換為 Python 物件。
    這個方法直接從 Book 模型中查詢所有書籍資料,並按書名升序排序,使用 all() 方法獲取所有的結果。
    '''
    with app.app_context():
   
        #列出所有結果
        db_rows = Book.query.order_by(Book.title).all()
        #查詢特定結果(數學)
        book = db.session.execute(db.select(Book).where(Book.title == "數學")).scalar()
        # print(f'book={book.title}')
        # print(f'book={book.author}')
        # print(f'book={book.rating}')
   
    return render_template("index.html", rows=db_rows,book=book)
   
   


Update A Particular Record By Query


Update A Record By PRIMARY KEY


# 假設你有一個書籍的 id,以及要更新的新資料

book_id_to_update = 1  # 這裡假設書籍的 id 是 1

new_data = {

    'title': '新書名',

    'author': '新作者',

    'rating': '⭐⭐⭐⭐'

}


# 使用 SQLAlchemy 的 session 進行 UPDATE 操作

with app.app_context():

    book_to_update = Book.query.get(book_id_to_update)

    

    if book_to_update:

        book_to_update.title = new_data['title']

        book_to_update.author = new_data['author']

        book_to_update.rating = new_data['rating']

        

        db.session.commit()

        print("更新成功")

    else:

        print("找不到指定的書籍")




Delete A Particular Record By PRIMARY KEY

You can also delete by querying for a particular value e.g. by title or one of the other properties. Again, the get_or_404() method is quite handy.


# 假設你有一個書籍的 id,以及要刪除的書籍

book_id_to_delete = 2  # 這裡假設書籍的 id 是 2


# 使用 SQLAlchemy 的 session 進行 DELETE 操作

with app.app_context():

    book_to_delete = Book.query.get(book_id_to_delete)

    

    if book_to_delete:

        db.session.delete(book_to_delete)

        db.session.commit()

        print("刪除成功")

    else:

        print("找不到指定的書籍")




這裡的關鍵是使用 db.session.commit() 來確認更改。在這之前,你可以在 db.session 上進行多次更新或刪除操作,而一次性提交所有更改。

請注意,query.get() 方法用於根據主鍵檢索單個對象,因此需要知道要更新或刪除的書籍的主鍵(通常是 id)。這樣的主鍵值應該是唯一的,以確保你準確地指定了要更新或刪除的書籍。




from flask import Flask, render_template, request, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField,SelectField
from wtforms.validators import DataRequired,URL
from flask_bootstrap import Bootstrap5
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
# configure the SQLite database, relative to the app instance folder
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///new-books-collection.db"
db = SQLAlchemy()
# initialize the app with the extension
db.init_app(app)

app.secret_key='dskja;djsaklu'
bootstrap5=Bootstrap5(app)
class MyForm(FlaskForm):
    Name=StringField("書名:",validators=[DataRequired()])
    Author = StringField("作者:",validators=[DataRequired()])
    Rating = SelectField("評價:",choices=['⭐','⭐⭐','⭐⭐⭐','⭐⭐⭐⭐','⭐⭐⭐⭐⭐'],validate_choice=True)
    Submit = SubmitField("儲存")
   
class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True,autoincrement=True)
    title = db.Column(db.String(250), unique=True, nullable=False)
    author = db.Column(db.String(250), nullable=False)
    rating = db.Column(db.String(250), nullable=False)

    # def __repr__(self):
    #     '''
    #     這是一個可選的方法,
    #     用於定義在打印 Book 物件時的格式。
    #     例如,當你使用 print(book) 時,
    #     它會返回 <Book 書名> 的格式。
    #     '''
    #     return f'<Book {self.title}>'

# Create table schema in the database. Requires application context.
with app.app_context():
    db.create_all()





all_books = []



@app.route('/')
def home():
    #讀取db
    '''
    Book.query.order_by(Book.title).all()
    使用 SQLAlchemy 提供的 ORM (Object-Relational Mapping) 操作,這是更高層次的抽象,它將資料庫查詢轉換為 Python 物件。
    這個方法直接從 Book 模型中查詢所有書籍資料,並按書名升序排序,使用 all() 方法獲取所有的結果。
    '''
    with app.app_context():
   
        #列出所有結果
        db_rows = Book.query.order_by(Book.title).all()
        #查詢特定結果(數學)
        book = db.session.execute(db.select(Book).where(Book.title == "數學")).scalar()
        # print(f'book={book.title}')
        # print(f'book={book.author}')
        # print(f'book={book.rating}')
   
    return render_template("index.html", rows=db_rows,book=book)
   
@app.route("/edit",methods=['GET','POST'])
def edit():
   
    id = request.args.get("id",None)
    print(f'id={id},type={type(id)}')
    with app.app_context():
        book = db.session.execute(db.select(Book).where(Book.id==id)).scalar()
   
    #當點擊確認按鈕後這邊要取得input內容
    if request.method =='POST':
        new_rating= request.form.get('new_rating')

        print(f'取得使用者輸入內容={new_rating}')
        with app.app_context():
            # book_update = db.session.execute(db.select(Book).where(Book.id==id)).scalar()
            book_update = db.get_or_404(Book,id)
            book_update.rating=new_rating
            db.session.commit()
        return redirect(url_for('home'))
   
    return render_template('select.html',book=book)

@app.route("/del",methods=['GET','POST'])
def del_book():
    id = request.args.get("id",None)
    with app.app_context():
        book = db.get_or_404(Book,id)
    print(f'確認查詢參數id={id}')
    if request.method=="POST":
        with app.app_context():#建立上下文連接
            book_data = db.get_or_404(Book,id)
            db.session.delete(book_data)
            db.session.commit()
        return redirect(url_for('home'))
    return render_template('del.html',book=book)




@app.route("/add",methods=['GET','POST'])
def add():
    form = MyForm()
    if form.validate_on_submit():
        print("新增成功")
        print(f"書名:{form.Name.data}")
        New_data={
            form.Name.label.text:form.Name.data,
            form.Author.label.text:form.Author.data,
            form.Rating.label.text:form.Rating.data}
       
        all_books.append(New_data)
        print(f"書單={all_books}")
        #新增Record
        with app.app_context():
            new_book = Book(title=form.Name.data,author=form.Author.data,rating=form.Rating.data)
            db.session.add(new_book)
            db.session.commit()
       
           

        return redirect(url_for('home'))

    return render_template('add.html',form=form)


if __name__ == "__main__":
    app.run(debug=True,port=5005)



------------index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Library</title>
  </head>
  <body>
    <h1>My Library</h1>
    {% if not rows %}
    <p>Library is empty~~~</p>
    {% else %}
    {% for row in rows %}
    <ul>
      <li>{{row.title}}</li>
      <li>{{row.author}}</li>
      <li>{{row.rating}}</li>
      <li><a href="{{url_for('edit',id=row.id)}}">修 改 評 價</a></li>
      <li><a href="{{url_for('del_book',id=row.id)}}">刪 除 該 本</a></li>
      <br>
    </ul>
    {% endfor %}
    {% endif %}
   
   

    <a href="{{url_for('add')}}">新 增 書 籍</a>
  </body>
</html>


----------select.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{book.title}}</title>
</head>
<body>
    <h1>查詢結果</h1>
    <ul>
   
   
    {% if book %}
    <li>{{book.title}}</li>
    <li>{{book.author}}</li>
    <li>{{book.rating}}</li>
    <form action="{{url_for('edit',id=book.id)}}" method="post">
    <input type="text" name="new_rating">
    <button type="submit">確認</button>
    </form>
   

    {% else %}
    <li>查詢結果不存在</li>
    {% endif %}


</ul>
<a href="{{url_for('home')}}">回 首 頁</a>
</body>
</html>



-----del.html

<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>book.title</title>
</head>
<body>
    <form action="{{url_for('del_book',id=book.id)}}" method="post">
        {{book.title}}
        <br>
        {{book.author}}
        <br>
        {{book.rating}}
        <br>
        <button type="submit" > 確 認 刪 除 </button>

    </form>


</body>
</html>


------------add.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Add Book</title>
   
    {% from 'bootstrap5/form.html' import render_form %}
  </head>
  <body>
    {{render_form(form)}}
    <!-- <form action="" method="POST">
      <label>Book Name</label>
      <input type="text" />
      <label>Book Author</label>
      <input type="text" />
      <label>Rating</label>
      <input type="text" />
      <button type="submit">Add Book</button>
    </form> -->
  </body>
</html>





















































標籤:

0 個意見:

張貼留言

訂閱 張貼留言 [Atom]

<< 首頁