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

400 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 介绍
`SQLAlchemy`是一个数据库的`ORM`框架,让我们操作数据库的时候不要再用`SQL`语句了,跟直接操作模型一样。安装命令为:`pip install SQLAlchemy`
# 连接数据库
前面的学习我们已经掌握了如何在本地部署mysql服务了现在将mysql启动之后创建测试的数据库
- 点击`start.bat` 启动mysql数据库
![image-20241219144614007](./01.SQLAlchemy/image-20241219144614007.png)
- 点击`connect.bat` 连接到数据库中
![image-20241219144653494](./01.SQLAlchemy/image-20241219144653494.png)
- 输入如下命令创建数据库
```sql
create database login;
show databases;
```
![image-20241219144732276](./01.SQLAlchemy/image-20241219144732276.png)
- 执行下面的代码
```python
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` 中,一个表就对应一个类,所以想要创建对应的表,就要先把类创建好
- 在类中,我们可以定义这个表中应该有哪些数据
```python
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会自动处理好幂等性
```
- 代码运行后,可以查看数据库中已经存在对应的表,并且按照要求创建好
```sql
use login
show tables;
explain user;
```
![image-20241219145706987](./01.SQLAlchemy/image-20241219145706987.png)
# 插入数据
- 创建一个网页,当我们访问这个页面的时候就插入多个用户
```python
@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](./01.SQLAlchemy/image-20241219150537129.png)
- 从命令行里面查看,确认数据都已经创建
```sql
mysql> select * from user;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | user01 | 123456 |
| 2 | user02 | 123456 |
| 3 | user03 | 123456 |
+----+----------+----------+
3 rows in set (0.00 sec)
```
# 查询数据
- 单独写一个页面用于用户数据的查询
```python
@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](./01.SQLAlchemy/image-20241219152029971.png)
# 登录功能实现
## 登录页面
- 创建模板的文件夹`templates`,并且将前面的登录注册页面放进去
![image-20241219152938127](./01.SQLAlchemy/image-20241219152938127.png)
- 编写python代码将登录页渲染到模版中
```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](./01.SQLAlchemy/image-20241219153544582.png)
## 后端业务逻辑
- 修改前端源码,将注册按钮跳转地址改为`/register`
![image-20241219153752702](./01.SQLAlchemy/image-20241219153752702.png)
- 修改python代码
- 增加允许的提交方法是`POST`
- 接受用户名和密码,并且拉入数据库进行比对
- 返回登录结果
```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("/", 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代码将注册页渲染到模版中
```python
@app.route("/register", methods=['GET', 'POST'])
def register():
return render_template("register.html")
```
- 访问效果如下
![image-20241219154701791](./01.SQLAlchemy/image-20241219154701791.png)
## 后端业务逻辑
- 修改`register.html`中的跳转代码。点击登录,可以正确的跳转到登录页面
![image-20241219154828636](./01.SQLAlchemy/image-20241219154828636.png)
- 修改python代码
- 获取前端输入的用户名和两次输入的密码
- 如果用户名已存在就直接显示用户名已存在
- 用户名不存在,但是两次密码不一样,就直接显示两次密码不一致
- 如果用户名不存在,且密码符合要求,就将用户名和密码加入数据库中,直接显示注册成功
```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](./01.SQLAlchemy/image-20241219164014985.png)