Friday, July 5, 2024

[Flask] – Phần 9: Tạo Database với SQLAlchemy sử dụng SQLite

-

Bài trước chúng ta đã tìm hiểu SQLAlchemy là gì rồi, bài này chúng ta hãy thử thực hành tạo Database bằng SQLAlchemy nhé.

Trong môi trường ảo bạn hãy cài đặt SQLAlchemy bằng lệnh pip install sqlalchemy.

$ pip install Flask-SQLAlchemy
Collecting sqlalchemy
  Downloading SQLAlchemy-2.0.20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.0 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.0/3.0 MB 11.9 MB/s eta 0:00:00
Collecting greenlet!=0.4.17
  Downloading greenlet-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (613 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 613.7/613.7 KB 23.2 MB/s eta 0:00:00
Collecting typing-extensions>=4.2.0
  Downloading typing_extensions-4.7.1-py3-none-any.whl (33 kB)
Installing collected packages: typing-extensions, greenlet, sqlalchemy
Successfully installed greenlet-2.0.2 sqlalchemy-2.0.20 typing-extensions-4.7.1

Hãy xây dựng project của bạn theo cấu trúc như dưới đây.

../myapp/
├── SQLAlchemy.py
└── templates
    ├── base.html
    ├── home.html
    ├── login.html
    └── user.html

Các file login.html, base.htmlhome.html mình sẽ giữ nguyên ở bài trước.

Nội dung file user.html.

{% extends "base.html" %}
{% block title %}Login Page{% endblock %}

{% block content %}
<h2>Hello {{user}}</h2>
{% with messages = get_flashed_messages() %}
    {% if messages %}
        {% for m in messages %}
            <p>{{m}}</p>
        {% endfor %}
    {% endif %}
{% endwith %}
<div style="margin-left: 50px;">
    <form action="#" method="post">
        <label for="email">Email</label>
        <input type="email" name="email" placeholder="Enter email..." value="{{email if email}}"></input>
        <button style="background-color: slateblue; color: white;" type="submit">Submit</button>
        <input type="name" name="name" placeholder="Enter name..." value="{{user if user}}"></input>
        <button style="background-color: slateblue; color: white;" type="submit">Delete</button>
    </form>
</div>
{% endblock %}

Đoạn code HTML trên mình chỉnh sửa phần (form) trong trang web và dưới đây là giải thích từng phần của nó:

  • <form action="#" method="post">: Đây là phần bắt đầu của form. Nó khai báo một form HTML và xác định hai thuộc tính quan trọng:
    • action="#": Đây là URL mà form sẽ gửi dữ liệu đến khi người dùng ấn nút “Submit.” Trong trường hợp này, # có nghĩa là form sẽ gửi dữ liệu đến chính trang hiện tại. Thường thì bạn sẽ cung cấp một URL cụ thể để xử lý dữ liệu gửi đi.
    • method="post": Đây là phương thức HTTP được sử dụng để gửi dữ liệu từ form đến máy chủ web. Trong trường hợp này, nó sử dụng phương thức POST, nghĩa là dữ liệu sẽ được gửi một cách an toàn và không hiển thị trực tiếp trong URL.
  • <label for="email">Email</label>: Đây là một nhãn (label) cho trường nhập (input) bên dưới. for="email" xác định rằng nhãn này ánh xạ với trường nhập có thuộc tính id="email". Nhãn này giúp người dùng hiểu rõ trường nhập là để nhập địa chỉ email.
  • <input type="email" name="email" placeholder="Enter email..." value="{{email if email}}">: Đây là trường nhập (input field) cho email. Các thuộc tính quan trọng bao gồm:
    • type="email": Xác định kiểu của trường nhập là email, giúp trình duyệt kiểm tra xem giá trị nhập vào có đúng định dạng email hay không.
    • name="email": Đây là tên của trường nhập, sẽ được sử dụng để xác định giá trị của trường này khi form được gửi đi.
    • placeholder="Enter email...": Đây là một gợi ý (placeholder) hiển thị trong trường nhập khi chưa có giá trị nào được nhập. Trong trường hợp này, nó nói cho người dùng biết rằng họ nên nhập địa chỉ email vào trường này.
    • value="{{email if email}}": Đây là giá trị mặc định của trường nhập. Nếu có biến email được truyền vào từ phía máy chủ (thông qua template Flask), thì giá trị này sẽ là giá trị của biến email. Điều này giúp hiển thị lại giá trị đã được người dùng nhập trước đó nếu có lỗi trong quá trình xử lý form.
  • <button style="background-color: slateblue; color: white;" type="submit">Submit</button>: Đây là nút “Submit” cho form. Nút này cho phép người dùng ấn để gửi dữ liệu form đến máy chủ. Thuộc tính style được sử dụng để tùy chỉnh giao diện của nút, trong trường hợp này, nút có màu nền là slateblue và màu chữ là trắng.
  • Ở nút Delete tương tự như Submit nhé.

Nội dung file SQLAlchemy.py.

from flask import Flask, redirect, url_for, render_template, request, session
from datetime import timedelta
from flask.helpers import flash
from flask_sqlalchemy import SQLAlchemy
from os import path

app = Flask(__name__)
app.config["SECRET_KEY"] = "hoanghd-secret-key"
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///user.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.permanent_session_lifetime = timedelta(minutes=1)

db = SQLAlchemy(app)

class User(db.Model):
    user_id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))
    email = db.Column(db.String(100))

    def __init__(self, name, email):
        self.name = name
        self.email = email

@app.route('/home')
def hello_world():
    return render_template("home.html")

@app.route('/login', methods=["POST", "GET"])
def login():
    if request.method == "POST":
        user_name = request.form["name"]
        session.permanent = True
        if user_name:
            session["user"] = user_name
            found_user = User.query.filter_by(name=user_name).first()
            if found_user:
                session["email"] = found_user.email
            else:
                user = User(user_name, "temp@gmail.com")
                db.session.add(user)
                db.session.commit()
                flash("Created in DB!")
            return redirect(url_for("user"))
    if "user" in session:
        return redirect(url_for("user"))
    return render_template("login.html")

@app.route("/user", methods=["POST", "GET"])
def user():
    email = None
    if "user" in session:
        name = session["user"]
        if request.method == "POST":
            if not request.form["email"] and request.form["name"]:
                User.query.filter_by(name=name).delete()
                db.session.commit()
                flash("Deleted user!")
                return redirect(url_for("log_out"))
            else:
                email = request.form["email"]
                session["email"] = email
                found_user = User.query.filter_by(name=name).first()
                found_user.email = email
                db.session.commit()
                flash("Email updated!")
        return render_template("user.html", user=name, email=email)
    else:
        return redirect(url_for("login"))

@app.route("/logout")
def log_out():
    session.pop("user", None)
    return redirect(url_for("login"))

if __name__ == "__main__":
    with app.app_context():
        if not path.exists("user.db"):
            db.create_all()
            print("Created database!")
    app.run(debug=True, host='0.0.0.0', port=5000)

Đoạn code trên dùng để tạo một ứng dụng web sử dụng Flask và SQLAlchemy để quản lý người dùng.

  • app.config: Đây là cấu hình của ứng dụng Flask. Bạn đã cấu hình các biến cơ bản cho ứng dụng:
    • "SECRET_KEY": Một khóa bí mật được sử dụng để bảo mật ứng dụng.
    • "SQLALCHEMY_DATABASE_URI": Đường dẫn tới cơ sở dữ liệu SQLite ("sqlite:///user.db").
    • "SQLALCHEMY_TRACK_MODIFICATIONS": Vô hiệu hóa theo dõi sự thay đổi của SQLAlchemy.
  • app.permanent_session_lifetime: Đặt thời gian sống của phiên (session) là 1 phút. Sau 1 phút, phiên sẽ hết hiệu lực và người dùng sẽ cần đăng nhập lại.
  • db = SQLAlchemy(app): Khởi tạo đối tượng SQLAlchemy để làm việc với cơ sở dữ liệu. Ứng dụng sử dụng SQLAlchemy để tạo và quản lý cơ sở dữ liệu SQLite.
  • class User(db.Model): Định nghĩa một lớp User là một model trong cơ sở dữ liệu. Lớp này có các trường như user_id, name, và email, và sử dụng SQLAlchemy để ánh xạ các trường này vào cơ sở dữ liệu SQLite.
  • @app.route('/home'): Định nghĩa một route (đường dẫn) có URL “/home” cho trang chủ của ứng dụng. Khi người dùng truy cập “/home”, hàm hello_world() sẽ được gọi và trả về trang HTML “home.html” thông qua render_template.
  • @app.route('/login', methods=["POST", "GET"]): Định nghĩa một route “/login” cho trang đăng nhập. Nó xử lý cả phương thức GET và POST. Nếu người dùng gửi một form POST (đăng nhập), nó kiểm tra thông tin đăng nhập, thực hiện đăng nhập và tạo hoặc cập nhật dữ liệu người dùng trong cơ sở dữ liệu.
  • @app.route("/user", methods=["POST", "GET"]): Định nghĩa một route “/user” cho trang thông tin người dùng. Nó xử lý cả phương thức GET và POST. Nếu người dùng đã đăng nhập, họ có thể cập nhật thông tin cá nhân của họ, bao gồm cả email.
  • @app.route("/logout"): Định nghĩa một route “/logout” cho trang đăng xuất. Khi người dùng ấn nút đăng xuất, phiên của họ sẽ bị xóa và họ sẽ được chuyển về trang đăng nhập.
  • Trong hàm if __name__ == "__main__":, bạn kiểm tra xem ứng dụng có đang được chạy trực tiếp hay không. Nếu nó được chạy trực tiếp, bạn sử dụng app.app_context() để đảm bảo rằng tạo cơ sở dữ liệu (db.create_all()) xảy ra trong một context ứng dụng Flask. Nếu tệp cơ sở dữ liệu “user.db” không tồn tại, nó sẽ tạo nó và in ra thông báo “Created database!”. Sau đó, ứng dụng sẽ được chạy trên cổng 5000.

Chạy ứng dụng của bạn lên.

$ python SQLAlchemy.py 
Created database!
 * Serving Flask app 'SQLAlchemy'
 * Debug mode: on
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://192.168.13.200:5000
Press CTRL+C to quit
 * Restarting with stat
Created database!
 * Debugger is active!
 * Debugger PIN: 947-129-701

Đây là kết quả khi chạy app, bạn sẽ nhìn thấy thông báo Created database sẽ được tạo nếu nó chưa tồn tại. Và trong thư mục myapp/instance bạn sẽ được khởi tạo một db mới tên là user.db.

myapp/
├── SQLAlchemy.py.py
├── instance
│   └── user.db
└── templates
    ├── base.html
    ├── home.html
    ├── login.html
    └── user.html

Khi bạn chạy ứng dụng xong, DB và Table của bạn sẽ tự động tạo theo yêu cầu của code Python ở trên.

Và đây là dữ liệu của bạn khi bạn thêm một thông tin mới.

Kết quả.

Tới đây bạn đã biết cách sử dụng SQLAlchemy để tạo một CSDL rồi, chúc các bạn thành công.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories