SQLAlchemy 是一种 ORM 框架,通过使用它,可以大大简化我们对数据库的操作,不用再写各种复杂的
sql语句
了。
说明
- 操作系统:Windows 10
- Python 版本:3.7x
- 虚拟环境管理器:virtualenv
- 代码编辑器:VS Code
实验目标
实现网站与 mysql 数据库的连接和 CRUD 操作。
MYSQL 的安装与配置
打开 Ubuntu 16.04 的 bash 界面,执行下述操作
# 安装sudo apt update && sudo apt install mysql-server mysql-clientsudo service mysql status# 配置安全性sudo mysql_secure_installationsudo mysqladmin -p -u root version# 查看状态sudo service mysql statussudo service mysql startsudo service mysql stop# 设置字符编码sudo vim /etc/mysql/conf.d/mysql.cnf# 修改如下:[mysql]no-auto-rehashdefault-character-set=utf8[mysqld]socket = /var/run/mysqld.sockport =3306character-set-server=utf8 # 必须设置,否则会导致无法插入中文数据# 重启服务sudo service mysql restart
mysql 常用用法
# 进入 mysqlmysql -u root -p# 查看当前字符编码show variables like 'character%';# 创建数据库 db_namecreate database db_name charset=utf8;# 显示以存在的所有数据库show databases;# 指定数据库 db_nameuse db_name;# 创建数据库表create table table_name;# 查看表信息desc tablename;# 删除 数据库 db_namedrop database db_name;# 退出exit;
使用 SQLAlchemy
首先进入 mysql 的控制台界面,创建我们需要使用的数据库
sudo mysql -u root -pcreate database todo;use todo;
安装 flask-sqlalchemy
pip install pymysqlpip install flask-sqlalchemy
在 todolist
目录下创建 config.py 文件,示例代码如下所示:
import osbasedir = os.path.abspath(os.path.dirname(__file__))class Config(object): SQLALCHEMY_DATABASE_URI = os.environ.get( 'SQLALCHEMY_DATABASE_URI') or 'mysql+pymysql://root:mysql@127.0.0.1:3306/todo' SQLALCHEMY_TRACK_MODIFICATIONS = False
修改 todolist\app\__init__.py
,示例代码如下所示:
from flask import Flask, render_templatefrom flask_sqlalchemy import SQLAlchemyfrom config import Configapp = Flask(__name__)app.config.from_object(Config)db = SQLAlchemy(app)@app.route('/')@app.route('/index')def index(): title = 'Home' greet = 'Hello World' return render_template('index.html', title=title, greet=greet)
在 todolist
目录下创建 models.py 文件,示例代码如下所示:
from app import dbfrom datetime import datetimeclass User(db.Model): __tablename__ = 'users' # __table_args__ = {"useexisting": True} id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(20), nullable=False, unique=True) email = db.Column(db.String(120), nullable=False, unique=True) pwd = db.Column(db.String(120), nullable=False) things = db.relationship('Thing', backref='User', lazy='dynamic') def __repr__(self): return "" % self.nameclass Thing(db.Model): __tablename__ = 'things' # __table_args__ = {"useexisting": True} id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id')) title = db.Column(db.String(20), nullable=False) text = db.Column(db.Text, nullable=False) add_date = db.Column(db.DateTime, default=datetime.now) def __repr__(self): return " " % self.id
修改 todolist\manage.py
,示例代码如下所示:
from app import app, dbfrom models import User, Thingfrom werkzeug.security import generate_password_hashif __name__ == "__main__": db.drop_all() db.create_all() pwd = generate_password_hash('123456789') u1 = User(name='admin', email='admin@outlook.com', pwd=pwd) db.session.add(u1) db.session.commit() t1 = Thing(user_id=1, title='hello world', text='welcome to my hippiedom.') db.session.add(t1) db.session.commit() u2 = User.query.get(1) print(u2) app.run(debug=True, host='0.0.0.0', port=5000)
此时,执行 python manage.py
,若程序无数据库相关的错误信息,则表明数据库中相应表已经创建成功,我们可以在 mysql 的 shell 窗口进行查看。
SQLAlchemy常用操作:
查询所有用户数据 User.query.all() 查询有多少个用户 User.query.count() 查询第1个用户 User.query.first() User.query.get(1) # 根据id查询 查询id为4的用户[3种方式] User.query.get(4) User.query.filter_by(id=4).all() # 简单查询 使用关键字实参的形式来设置字段名 User.query.filter(User.id == 4).all() # 复杂查询 使用恒等式等其他形式来设置条件 查询名字结尾字符为g的所有用户[开始 / 包含] User.query.filter(User.name.endswith("g")).all() User.query.filter(User.name.startswith("w")).all() User.query.filter(User.name.contains("n")).all() User.query.filter(User.name.like("%n%g")).all() 模糊查询 查询名字和邮箱都以li开头的所有用户[2种方式] User.query.filter(User.name.startswith("li"), User.email.startswith("li")).all() from sqlalchemy import and_ User.query.filter(and_(User.name.startswith("li"), User.email.startswith("li"))).all() 查询age是25 或者 `email`以`itheima.com`结尾的所有用户 from sqlalchemy import or_ User.query.filter(or_(User.age == 25, User.email.endswith("itheima.com"))).all() 查询名字不等于wang的所有用户[2种方式] from sqlalchemy import not_ User.query.filter(not_(User.name == "wang")).all() User.query.filter(User.name != "wang").all() 查询id为[1, 3, 5, 7, 9]的用户 User.query.filter(User.id.in_([1, 3, 5, 7, 9])).all() 所有用户先按年龄从小到大, 再按id从大到小排序, 取前5个 User.query.order_by(User.age, User.id.desc()).limit(5).all() 分页查询, 每页3个, 查询第2页的数据 pn = User.query.paginate(2, 3) pn.items 获取该页的数据 pn.page 获取当前的页码 pn.pages 获取总页数
常用 API 参考
# 基本使用db.drop_all()db.create_all()db.session.add(对象)db.session.commit()# 数据类型db.Integer:整型db.String (size):字符串,size 为最大长度,比如 db.String(20)db.Text:长文本db.DateTime:时间日期,Python datetime 对象db.Float:浮点数db.Boolean:布尔值# 过滤方法格式: <模型类> .query. <过滤方法(可选)> . <查询方法> filter():使用指定的规则过滤记录,返回新产生的查询对象filter_by():使用指定规则过滤记录(以关键字表达式的形式),返回新产生的查询对象order_by():根据指定条件对记录进行排序,返回新产生的查询对象group_by():根据指定条件对记录进行分组,返回新产生的查询对象# 查询方法all():返回包含所有查询记录的列表first():返回查询的第一条记录,如果未找到,则返回Noneget(id):传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回Nonecount():返回查询结果的数量first_or_404():返回查询的第一条记录,如果未找到,则返回404错误响应get_or_404(id):传入主键值作为参数,返回指定主键值的记录,如果未找到,则返回404错误响应paginate():返回一个Pagination对象,可以对记录进行分页处理 查询方法> 过滤方法(可选)> 模型类>