Flask框架下使用SQLAlchemy搭建用户类User来操纵数据库

时间:2024-10-15 13:12:27

         在面向对象的编程语言(如 Python、Java、C# 等)中,使用类来表示用户信息是很常见的做法。例如,在 Python 的 Flask 或 Django 框架中,可以使用类来定义用户模型。而使用用户类在数据库中维护一个用户数据模型,可以有效地管理和持久化用户信息

在实际应用中,验证会话和用户类通常是结合使用的:

  1. 登录阶段:用户提交登录表单时,使用用户类验证用户的身份。
  2. 会话管理:验证成功后,使用会话存储用户标识符(如用户ID),在后续的请求中根据会话判断用户是否已登录。

User类示例(Python/Flask/SQLAlchemy):

定义模型类(指定表)

  • 每个模型类对应数据库中的一个表。
  • 模型类通过继承 db.Model 来指定表结构。
  • 每个类属性对应表中的一个字段。 
from flask_sqlalchemy import SQLAlchemy

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
db = SQLAlchemy(app)  # 这里使用的是sqlite数据库,并指定使用的数据库为users

class User(db.Model):
    __tablename__ = 'users'  # 显式指定表名,如果不指定,SQLAlchemy 会默认使用类名的小写形式作为表名
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)

User 模型的组件

  1. 数据库模型User 类继承自 db.Model,这表明它是一个 SQLAlchemy 模型,允许与数据库进行交互。

  2. 属性定义: 模型类通常定义一些属性,以表示用户数据在数据库表中的各个列。这些属性通过 SQLAlchemy 的列类型定义。

  3. 构造方法: 可以定义一个构造函数 __init__,用于方便地创建 User 实例。

ORM:

        这里需要介绍一下什么是ORM,不然读者可能不明白为什么能够使用用户类来实现对数据库的操作。ORM(对象关系映射)是一个用于处理数据库操作的技术,它允许开发者使用对象而不是 SQL 语言来操作数据库。而上面我们使用的SQLAlchemy 是一个流行的 Python ORM 框架。

       在 Flask 应用中,class User(db.Model): 是定义一个用户模型的代码段。这个模型类通常用于与数据库交互,特别是使用 Flask-SQLAlchemy 这个扩展来管理数据库操作。下面是对User模型及其各个部分的详细解释,并附上完整的代码示例,展示如何定义和使用这个模型。

完整示例

以下是一个完整的 Flask 应用示例,包括定义用户模型 (User)、初始化数据库、用户注册和登录的逻辑。

from flask import Flask, request, session, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
app.secret_key = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

# 定义 User 模型
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)  # 主键
    username = db.Column(db.String(80), unique=True, nullable=False)  # 唯一用户名
    password = db.Column(db.String(120), nullable=False)  # 哈希后的密码

    def __repr__(self):
        return f'<User {self.username}>'

# 初始化数据库
with app.app_context():
    db.create_all()  # 创建数据库表

# 用户注册
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        
        if User.query.filter_by(username=username).first():
            flash('Username already exists.')
            return redirect(url_for('register'))

        hashed_password = generate_password_hash(password, method='sha256')
        new_user = User(username=username, password=hashed_password)
        db.session.add(new_user)
        db.session.commit()
        
        flash('Registered successfully!')
        return redirect(url_for('login'))
    return '''
        <form method="post">
            Username: <input type="text" name="username"><br>
            Password: <input type="password" name="password"><br>
            <input type="submit" value="Register">
        </form>
    '''

# 用户登录
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        user = User.query.filter_by(username=username).first()
        if user and check_password_hash(user.password, password):
            session['user_id'] = user.id  # 将用户ID存入会话
            flash('Logged in successfully!')
            return redirect(url_for('profile'))
        else:
            flash('Invalid username or password.')
            return redirect(url_for('login'))
    return '''
        <form method="post">
            Username: <input type="text" name="username"><br>
            Password: <input type="password" name="password"><br>
            <input type="submit" value="Login">
        </form>
    '''

# 用户个人资料页面
@app.route('/profile')
def profile():
    if 'user_id' in session:
        user = User.query.get(session['user_id'])  # 获取当前用户的信息
        return f'Welcome, {user.username}!'
    return redirect(url_for('login'))

# 用户登出
@app.route('/logout')
def logout():
    session.pop('user_id', None)  # 清除会话
    flash('Logged out successfully!')
    return redirect(url_for('login'))

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

解释代码部分

  • new_user 是 User 类的一个实例,而 User 类是 SQLAlchemy 模型的一部分。
  • db.session.add(new_user) 会将 new_user 对象添加到当前的 SQLAlchemy 会话中,SQLAlchemy 能够识别并跟踪这个对象。
  • 最终,通过 db.session.commit(),SQLAlchemy 会将 new_user 对象持存储到数据库中
  • user = User.query.filter_by(username=username).first() 这行代码的作用是从数据库的表中查询第一个 User 对象。因为在 ORM 中,数据库表被映射为类,表的每一行则被映射为类的一个实例(对象)。
  • 数据库设置:

    • 使用 SQLite 数据库,并配置数据库 URI。
    • db.Model 是 SQLAlchemy 提供的基础模型,User 类通过继承它来与数据库交互。
  • 注册和登录流程:

    • register 路由处理用户注册,首先检查用户名是否已经存在,然后将用户信息保存到数据库。
    • login 路由验证用户名和密码,如果验证成功,将用户 ID 存储在会话中,以维持登录状态。
  • 个人资料页面:

    • 检查用户是否已登录,如果已登录则显示用户信息,否则重定向到登录页。