Đây là Bài 3 trong chuối các bài hướng dẫn sử dụng Python Flask cơ bản. Xem Bài 2: Thiết lập khung sản phẩm
Để truy vấn được với cơ sở dữ liệu sqlite, trước hết chúng ta cần thiết lập kết nối (database connection). Sử dụng đoạn code sau trong file mới my-customer/db.py:
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
# 1. Lấy đối tượng sử dụng để kết nối với csdl: "db"
# Nếu đối tượng "db" đã tồn tại, thì sử dụng lại kết nối đó để truy vấn. Còn không, chúng ta tạo kết nối mới.
# 2. Biến "current_app" là đối tượng đại diện cho app hiện tại của chúng ta.
def get_db():
if 'db' not in g:
# kết nối với csdl mang tên config['DATABASE'] đã được chúng ta khai báo trong file __init__.py
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
return g.db
# Đóng kết nối sau khi hoàn tất truy vấn
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
Dựa theo thông tin của sản phẩm, bảng cơ sở dữ liệu của chúng ta sẽ có cấu trúc như sau:
my-customer/schema.sql:
DROP TABLE IF EXISTS customer;
DROP TABLE IF EXISTS invoice;
CREATE TABLE customer (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT UNIQUE NOT NULL,
full_address TEXT,
phone_1 VARCHAR(100),
phone_2 VARCHAR(100),
email VARCHAR(100),
website VARCHAR(100),
remark TEXT
);
CREATE TABLE invoice (
id INTEGER PRIMARY KEY AUTOINCREMENT,
customer_id INTEGER NOT NULL,
invoice_date DATE,
description TEXT NOT NULL,
sub_total FLOAT,
discount FLOAT,
tax FLOAT,
FOREIGN KEY (customer_id) REFERENCES customer (id)
);
Chú ý, bảng invoice sẽ không có cột tổng giá trị sau VAT (tax) vì final total đó có thể tính theo phép toán:
final_total = sub_total - discount + tax.
Trong thiết kế cơ sở dữ liệu chuẩn NF, chúng ta không nên lưu trữ cột thông tin có giá trị từ phép tính dựa trên các cột khác trong bảng đó.
Bây giờ, chúng ta cập nhậy db.py để đọc schema và khởi tạo các bảng đã định nghĩa ở trên.
Update my-customer/db.py và thêm 2 hàm sau:
# mở file schema.sql và chạy các dòng sql.
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
@click.command('init-db') # thêm command init-db
@with_appcontext
def init_db_command():
"""xóa data hiện tại nếu có và tạo bảng"""
init_db()
click.echo('Database setup successfully.')
Tiếp theo, chúng ta khai báo 2 hàm close_db và init_db_command trên. Thêm đoạn code sau trong db.py:
def init_app(app):
# cho app biết cần gọi hàm close sau khi lấy xong data
app.teardown_appcontext(close_db)
# cho app biết có thể dùng command init-db trên termina/console để khởi tạo csdl. Chúng ta sẽ chạy command này để tạo bảng.
app.cli.add_command(init_db_command)
Và đăng ký my-customer/db trong trong my-customer/__init__.py của app để mọi hoạt động truy vấn trong app có thể được thực hiện:
def create_app():
app = ...
# Các đoạn code hiện tại
# ...
# thêm 2 dòng dưới đây:
from . import db
db.init_app(app)
return app
Xong! Cuối cùng bạn đã sẵn sàng để khởi tạo cơ sở dữ liệu của app rồi nhé. Chúng ta hãy cùng mở terminal/shell/console. Tại thư mục mẹ “flask-customer” của thư mục “my-customer”, chạy dòng lệnh:
$ flask init-db
Chú ý, nếu bạn chưa kích hoạt virtual environment, thì trước khi init-db, bạn cần phải kích hoạt lại. Chạy lệnh sau tại thư mục “flask-customer”:
$ . venv/bin/activate
$ export FLASK_APP=my-customer
Bài tiếp theo: Xây dựng web app với Blueprints và Views của Python Flask

