Files
python-flask/project14/01.SQLAlchemy.md
2025-09-11 16:13:52 +08:00

12 KiB
Raw Permalink Blame History

介绍

SQLAlchemy是一个数据库的ORM框架,让我们操作数据库的时候不要再用SQL语句了,跟直接操作模型一样。安装命令为:pip install SQLAlchemy

连接数据库

前面的学习我们已经掌握了如何在本地部署mysql服务了现在将mysql启动之后创建测试的数据库

  • 点击start.bat 启动mysql数据库

image-20241219144614007

  • 点击connect.bat 连接到数据库中

image-20241219144653494

  • 输入如下命令创建数据库
create database login;
show databases;

image-20241219144732276

  • 执行下面的代码
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text

app = Flask(__name__)

HOSTNAME = 'localhost'
# 数据库地址
PORT = 3306
# 数据库端口号
USERNAME = "root"
# 数据库用户名
PASSWORD = "usbw"
# 数据库密码
DATABASE = "login"
# 数据库名

app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}/{DATABASE}?charset=utf8'
# 配置flask连接数据库的配置

db = SQLAlchemy(app)
# 连接数据库,并且拿到连接的接口

with app.app_context():
    rs = db.session.execute(text('select 1'))
    # 执行一个测试的sql语句
    print(rs.fetchone())
    # 输出测试结果

创建表

  • flask_sqlalchemy 中,一个表就对应一个类,所以想要创建对应的表,就要先把类创建好
  • 在类中,我们可以定义这个表中应该有哪些数据
class User(db.Model):
    # 这个类是对应了user这个表
    __tablename__ = 'user'
    # 设置表的选项包括字符集为utf8
    __table_args__ = {
        'mysql_charset': 'utf8',
        'mysql_collate': 'utf8_general_ci'
    }
    # 设置表名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # 第一列数据列名为id后面对应的参数是(整数类型,主键,自动增长)
    username = db.Column(db.String(100), unique=True, nullable=False)
    # username列长度为100的字符串唯一不能为空
    password = db.Column(db.String(100), nullable=False)
    # password列长度为100的字符串不能为空


with app.app_context():
    # 如果想要在主程序中调用数据库,就要启动上下文管理
    db.create_all()
    # 创建对应的表不用担心反复创建sqlalchemy会自动处理好幂等性
  • 代码运行后,可以查看数据库中已经存在对应的表,并且按照要求创建好
use login
show tables;
explain user;

image-20241219145706987

插入数据

  • 创建一个网页,当我们访问这个页面的时候就插入多个用户
@app.route("/user/add")
def user_add():
    user1 = User(username="user01", password="123456")
    # 实例化一个用户对象
    user2 = User(username="user02", password="123456")
    user3 = User(username="user03", password="123456")
    db.session.add(user1)
    # 实例化一个用户对象将这个对象加到db接口中
    db.session.add(user2)
    db.session.add(user3)
    db.session.commit()
    # 提交更改的内容
    return "用户创建成功!"


app.run(debug=True, host="0.0.0.0", port=8000)
  • 访问此页面

image-20241219150537129

  • 从命令行里面查看,确认数据都已经创建
mysql> select * from user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | user01   | 123456   |
|  2 | user02   | 123456   |
|  3 | user03   | 123456   |
+----+----------+----------+
3 rows in set (0.00 sec)

查询数据

  • 单独写一个页面用于用户数据的查询
@app.route("/user/fetch")
def user_fetch():
    user = User.query.filter(and_(User.username == "user01", User.password == "123456")).all()
    # 获取用户对象,查询用户名和密码是否正确
    if len(user) == 0:
        # 如果查询到的结果是0说明没有用户名和密码是对的
        return "用户名或密码不正确"
    else:
        return f"欢迎用户{user[0].username}登录成功!"
  • 访问测试

image-20241219152029971

登录功能实现

登录页面

  • 创建模板的文件夹templates,并且将前面的登录注册页面放进去

image-20241219152938127

  • 编写python代码将登录页渲染到模版中
from flask import Flask, render_template

app = Flask(__name__)


@app.route("/")
def index():
    return render_template("login.html")


app.run(debug=True, host="0.0.0.0", port=8000)
  • 访问效果如下

image-20241219153544582

后端业务逻辑

  • 修改前端源码,将注册按钮跳转地址改为/register

image-20241219153752702

  • 修改python代码
    • 增加允许的提交方法是POST
    • 接受用户名和密码,并且拉入数据库进行比对
    • 返回登录结果
from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text, and_

app = Flask(__name__)

HOSTNAME = 'localhost'
# 数据库地址
PORT = 3306
# 数据库端口号
USERNAME = "root"
# 数据库用户名
PASSWORD = "123456"
# 数据库密码
DATABASE = "login"
# 数据库名

app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}/{DATABASE}?charset=utf8'
# 配置flask连接数据库的配置

db = SQLAlchemy(app)

class User(db.Model):
    # 这个类是对应了user这个表
    __tablename__ = 'user'
    # 设置表的选项包括字符集为utf8
    __table_args__ = {
        'mysql_charset': 'utf8',
        'mysql_collate': 'utf8_general_ci'
    }
    # 设置表名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # 第一列数据列名为id后面对应的参数是(整数类型,主键,自动增长)
    username = db.Column(db.String(100), unique=True, nullable=False)
    # username列长度为100的字符串唯一不能为空
    password = db.Column(db.String(100), nullable=False)
    # password列长度为100的字符串不能为空


with app.app_context():
    # 如果想要在主程序中调用数据库,就要启动上下文管理
    db.create_all()
    # 创建对应的表
@app.route("/", methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # 如果是post请求说明是提交过来的请求
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.query.filter(and_(User.username == username, User.password == password)).all()
        # 获取用户对象,查询用户名和密码是否正确
        if len(user) == 0:
            # 如果查询到的结果是0说明没有用户名和密码是对的
            return "用户名或密码不正确"
        else:
            return f"欢迎用户{user[0].username}登录成功!"
    return render_template("login.html")


app.run(debug=True, host="0.0.0.0", port=8000)
  • 在页面中测试登录成功或失败

注册功能实现

注册页面

  • 编写python代码将注册页渲染到模版中
@app.route("/register", methods=['GET', 'POST'])
def register():
    return render_template("register.html")
  • 访问效果如下

image-20241219154701791

后端业务逻辑

  • 修改register.html中的跳转代码。点击登录,可以正确的跳转到登录页面

image-20241219154828636

  • 修改python代码
    • 获取前端输入的用户名和两次输入的密码
    • 如果用户名已存在就直接显示用户名已存在
    • 用户名不存在,但是两次密码不一样,就直接显示两次密码不一致
    • 如果用户名不存在,且密码符合要求,就将用户名和密码加入数据库中,直接显示注册成功
from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text, and_

app = Flask(__name__)

HOSTNAME = 'localhost'
# 数据库地址
PORT = 3306
# 数据库端口号
USERNAME = "root"
# 数据库用户名
PASSWORD = "123456"
# 数据库密码
DATABASE = "login"
# 数据库名

app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}/{DATABASE}?charset=utf8'
# 配置flask连接数据库的配置

db = SQLAlchemy(app)


class User(db.Model):
    # 这个类是对应了user这个表
    __tablename__ = 'user'

    # 设置表的选项包括字符集为utf8
    __table_args__ = {
        'mysql_charset': 'utf8',
        'mysql_collate': 'utf8_general_ci'
    }

    # 设置表名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    # 第一列数据列名为id后面对应的参数是(整数类型,主键,自动增长)
    username = db.Column(db.String(100), unique=True, nullable=False)
    # username列长度为100的字符串唯一不能为空
    password = db.Column(db.String(100), nullable=False)
    # password列长度为100的字符串不能为空


with app.app_context():
    # 如果想要在主程序中调用数据库,就要启动上下文管理
    db.create_all()
    # 创建对应的表


@app.route("/user/add")
def user_add():
    user1 = User(username="user01", password="123456")
    # 实例化一个用户对象
    user2 = User(username="user02", password="123456")
    user3 = User(username="user03", password="123456")
    db.session.add(user1)
    # 实例化一个用户对象将这个对象加到db接口中
    db.session.add(user2)
    db.session.add(user3)
    db.session.commit()
    # 提交更改的内容
    return "用户创建成功!"


@app.route("/", methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # 如果是post请求说明是提交过来的请求
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.query.filter(and_(User.username == username, User.password == password)).all()
        # 获取用户对象,查询用户名和密码是否正确
        if len(user) == 0:
            # 如果查询到的结果是0说明没有用户名和密码是对的
            return "用户名或密码不正确"
        else:
            return f"欢迎用户{user[0].username}登录成功!"
    return render_template("login.html")


@app.route("/register", methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        confirm_password = request.form.get('confirmPassword')
        user = User.query.filter_by(username=username).all()
        # 判断用户名是否存在
        if len(user) > 0:
            print(user)
            return "用户名已存在"
        if password != confirm_password:
            # 判断两次密码是否一致
            return "两次密码不一致"
        temp_user = User(username=username, password=password)
        db.session.add(temp_user)
        db.session.commit()
        # 将用户名和密码加入数据库
        return "注册成功"
    return render_template("register.html")


app.run(debug=True, host="0.0.0.0", port=8000)
  • 最后测试一下是否能够正常的注册与登录

image-20241219164014985