《我用Python写网站02》数据库管理

30 阅读4分钟

使用sqlalchemy只需要:

User.query.all()

二者产生的结果完全相同,所以,选择Flask-SQLAlchemy没商量。

废话不多说,立即开始。

首先,进入上一篇已经建立好的ahoh文件夹,然后激活Python虚拟环境:

~$ cd ahoh

~/ahoh$ . venv/bin/activate

在使用Flask-SQLAlchemy之前,需要先安装对应的包,以及Mysql驱动程序pymysql

(venv)~/ahoh$ pip install pymysql

(venv)~/ahoh$ pip install flask-sqlalchemy

安装完成后,在~/ahoh/app.py文件中引入Flask-SQLAlchemy对应的类:

from flask_sqlalchemy import SQLAlchemy

然后在 app=Flask(__name__)语句后面添加配置对应的参数,并创建SQLAlchemy对象:

app.config.from_mapping(

SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:123456@localhost/ahoh?charset=utf8',

SQLALCHEMY_TRACK_MODIFICATIONS=True

)

db= SQLAlchemy(app)

SQLALCHEMY_DATABASE_URI变量的配置,就是为了向SQLAlchemy指明你使用的数据库类型、驱动、数据库用户名、密码、IP和数据库名,具体如下图:

SQLALCHEMY_DATABASE_URI的意义

然后,不要忘了,在Mysql中创建对应的数据库,这里使用的是ahoh,创建数据库命令如下:

create database ahoh;

到这里,Flask-SQLAlchemy插件的配置工作已经完成了,但是,现在还不能测试。

既然是对象关系映射(ORM)框架,必然还要提供对象,然后才能映射到关系表。

SQLAlchemy 对象


所谓SQLAlchemy对象,无非就是一个特殊的类,这里就直接在app.py文件的末尾,追加User类:

class User(db.Model):

tablename = 't_users' # 对应的数据库表名

id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 自增主键

username = db.Column(db.String(80), unique=True, nullable=False)

email = db.Column(db.String(120), unique=True)

password = db.Column(db.String(127), nullable=False)

这个类中的每一个属性,都对应数据库中表的一列,应该还是比较容易理解的,db.Integerdb.String是最常用的两个类型,SQLAlchemy还有很多其他类型的数据,后面后逐步扩展我们的代码。

为了保证大家都跟的上,下面贴出app.py的代码:

~/ahoh/app.py

from flask import Flask, render_template, request

from flask_sqlalchemy import SQLAlchemy

app = Flask(name)

app.config.from_mapping(

SQLALCHEMY_DATABASE_URI='mysql+pymysql://root:123456@localhost/ahoh?charset=utf8',

SQLALCHEMY_TRACK_MODIFICATIONS=True

)

db = SQLAlchemy(app)

@app.route('/')

def index():

return '你好, Flask'

... ... # 代码过长,此处省略其他视图函数

class User(db.Model):

tablename = 't_users'

id = db.Column(db.Integer, primary_key=True, autoincrement=True)

username = db.Column(db.String(80), unique=True, nullable=False)

email = db.Column(db.String(120), unique=True)

password = db.Column(db.String(127), nullable=False)

OK,到了这里,所有的sqlalchemy工作就算做完了,下面开始测试工作。

下面就用Flask Shell完成数据库中表的创建工作,测试代码正确性。

Flask Shell创建数据表


首先使用Ctrl+C停下正在运行的Flask服务,然后在命令行中输入:

(venv)~/ahoh$ flask shell # 启动Flask Shell

Python 3.8.10 (default, Nov 26 2021, 20:14:08)

[GCC 9.3.0] on linux

App: app [production]

Instance: /home/wei/ahoh/instance

                 # 出现命令提示符表示成功启动 

Flask ShellPython可交互编程环境差不多,我们不做深究,直接开始。

Shell中输入以下代码:

from app import db # 引入db变量

db.create_all() # 创建所有的表

以上指令,就会创建所有继承了db.Model的类对应的表了,如果在输入db.create_all()后没有任何输出(没有报错信息),大概率就是成功了。

然后,新开一个终端,进入Mysql查看ahoh数据库中是否真的创建了表:

mysql> use ahoh;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;

+----------------+

| Tables_in_ahoh |

+----------------+

| t_users |

+----------------+

1 row in set (0.00 sec)

mysql>

还可以使用 DESC指令查看表的结构:

mysql> desc t_users;

+----------+--------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+----------+--------------+------+-----+---------+----------------+

| id | int | NO | PRI | NULL | auto_increment |

| username | varchar(80) | NO | UNI | NULL | |

| email | varchar(120) | YES | UNI | NULL | |

| password | varchar(127) | NO | | NULL | |

+----------+--------------+------+-----+---------+----------------+

4 rows in set (0.00 sec)

mysql>

建表工作这里就完成了,下面测试数据表的增删改查。

回到Flask Shell,输入以下指令,向t_users表中插入数据:

from app import User # 引入User类

u = User(username='xiaoming',email='123@123.com',password='123456') # 创建User实例

db.session.add(u) # 向数据库添加新数据

db.session.commit() # 提交

如果执行以上指令之后,没有报错信息,就厉害大发了。

赶快回到Mysql查看一下t_users表里面到底有没有数据,使用以下指令:

mysql> select * from t_users; # 查询表中所有数据

+----+----------+-------------+----------+

| id | username | email | password |

+----+----------+-------------+----------+

| 1 | xiaoming | 123@123.com | 123456 |

+----+----------+-------------+----------+

1 row in set (0.00 sec)

输出和我一样就证明没有问题了!

提醒:密码明文存储是非常愚蠢的行为,这里仅供展示使用,后面会使用加密手段

这也是为什么密码列预留空间很大的原因,你发现了吗

只有一条数据肯定不像话,多加几条:

u1 = User(username='aaa',password='bbb',email="123@qwe.com")

u2 = User(username='eee',password='bbb',email="qwe@qwe.com")

db.session.add(u1)

db.session.add(u2)

db.session.commit()

然后测试删、改功能:

删除测试

u = User.query.filter_by(username='aaa').first() # 查询

u.username

'aaa'

db.session.delete(u) # 删除

db.session.commit()

修改测试

u = User.query.filter_by(username='xiaoming').first()

u.username

'xiaoming'

u.username='老天爷'

db.session.add(u)

db.session.commit()

Flask-Migrate数据库版本控制


现在数据库和Flask-SQLAlchemy插件都配置好了,新问题又来了。

我现在对数据表不满意,因为没有年龄age字段,而且我希望最终建立的数据库有很多表,和现在差距肯定非常大。

所以我需要不断的修改db.Model的子类,如何在每次修改对象类后,将改动同步到数据库呢?

这就需要Flask-Migrate插件了,首先,老规矩,安装插件:

(venv) ~/ahoh$ pip install flask-migrate

接下来就是配置Flask-Migrate插件,非常简单,先在app.py文件头部导入:

from flask_migrate import Migrate

然后在db=SQLAlchemy(app)后创建migrate实例:

migrate = Migrate(app, db)

这样就配置完成了。

Flask-Migrate的使用也很方便,包括三条命令

首先就是初始化命令:flask db init

在首次安装Flask-Migrate插件后,需要执行一次,后面就不需要了。

我们先初始化:

(venv) ~/ahoh$ flask db init

Creating directory /home/wei/ahoh/migrations ... done

Creating directory /home/wei/ahoh/migrations/versions ... done

Generating /home/wei/ahoh/migrations/script.py.mako ... done

Generating /home/wei/ahoh/migrations/env.py ... done

Generating /home/wei/ahoh/migrations/alembic.ini ... done

Generating /home/wei/ahoh/migrations/README ... done

Please edit configuration/connection/logging settings in '/home/wei/ahoh/migrations/alembic.ini' before

proceeding.

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

了解详情:docs.qq.com/doc/DSnl3ZG…