文章目录
1 ORM是什么
- ORM(Object Relational Mapping),对象关系映射
ORM的重要特性:
- 面向对象的编程思想,方便扩充
- 少写(几乎不写)SQL,提升开发效率
- 支持多种类型的数据库,方便切换
- ORM技术成熟,能解决绝大部分问题
2 flask-sqlalchemy介绍及安装、配置
安装
- 安装
pip安装:pip install -U Flask-SQLAlchemy
源码安装:python setup.py install
- 安装依赖
pip install mysqlclient
fask-sqlalchemy配置
-
数据库URI:
SQLALCHEMY_DATABASE_URI
统一资源标识符(Uniform resource Identifier,∪R|)是一个用于标识某一互联网资源名称的字符串
-
MySQL数据库URL参数格式
mysql: //scott: tiger@localhost/mydatabase
- 多个数据库支持
SQLALCHEMY_BINDS = {
'db1':'mysqldb://localhost/users',
'db2':'sqlit:path/to/appmeta.db'
}
创建数据库
3 设计数据库模型并创建表
数据库模型设计:
-
绑定到Fask对象
db = SQLAlchemy(app)
-
ORM模型创建
class User(db.Model): id = db.Column(db.Integer, primary_key=True)
-
指定表名称
__tablename__ = 'weibo_user_addr'
创建和删除表:
-
手动创建数据库
-
创建表
db.create_all(bind='db1')
-
删除表
db.drop_all()
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置数据库的连接参数
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@127.0.0.1/test_flask'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), nullable=False)
数据库模型设计:
- ORM模型字段类型支持
- 一对多关系,外键关联
user_id = db.Column(db.Integer, db.ForeignKey('weibo_user.id'), nullable=False)
- 一对多关系,外键关联
user = db.relationship('User', backref=db.backref('address', lazy=True))
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置数据库的连接参数
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root@127.0.0.1/test_flask'
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'weibo_user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), nullable=False)
password = db.Column(db.String(256), nullable=False)
birth_date = db.Column(db.Date, nullable=True)
age = db.Column(db.Integer, default=0)
class UserAddress(db.Model):
""" 用户的地址 """
__tablename__ = 'weibo_user_addr'
id = db.Column(db.Integer, primary_key=True)
addr = db.Column(db.String(256), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('weibo_user.id'), nullable=False)
user = db.relationship('User', backref=db.backref('address', lazy=True))
@app.route('/')
def mine():
""" 首页 """
return render_template('index.html')
4 使用OR M插入、修改、删除数据
新增/修改数据
-
构造ORM模型对象
usr = User('admin','admin@exapmle.com)
-
添加到db.session(备注:可添加多个对象)
db.session.add(user)
-
提交到数据库
db.session.commit()
新增用户
新增第二个
新增第三个
数据库结果:
修改:
物理删除数据:
-
查询ORM模型对象
user = User.query.filter_by(username='zhangsan').first()
-
添加到db.session
db.session.delete(user)
-
提交到数据库
db.session.commit()
5 使用ORM进行数据查询与展示
-
返回结果集(list)
-
查询所有数据
User.query.all()
-
按条件查询
User.query.filter_by(username='zhangsan')
User.query.filter(User.nickname.endswith('三')).all()
-
排序
User.query.order_by(User.username)
-
查询TOP10
User.query.limit(10).all()
-
-
返回单个ORM对象
-
更具PK(主键)查询
User.query.get(1)
-
获取第一条记录
User.query.first()
-
-
视图快捷函数:有则返回,无则返回404
- first() vs first_or_404()
- get() vs get_or_404()
-
多表关联查询
- db.session.query(User).join(Address)
- User.query.join(Address)
分页:
- 方式一:使用offset和limit
.offset(offset).limit(limit)
- 方式二:paginate分页支持
.paginte(page=2,per_page=4)
- 返回Pagination的对象
Pagination的对象:
-
has_prev/has_next——是否有上一页/下一页
-
Items——当前页的数据列表
-
prev_num/next_num——上一页/下一页的页码
-
total——总记录数
-
pages——总页数
结合模板实现分页:
-
第一步:准备数据
list_user = User.query.filter_by(is_valid=1)
-
第二步:分页
list_user.paginate(page=2, per_page=4)
-
第三步:在模板中实现分页操作
app.py
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置数据库的连接参数
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:@127.0.0.1/test_flask'
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'weibo_user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), nullable=False)
password = db.Column(db.String(256), nullable=False)
birth_date = db.Column(db.Date, nullable=True)
age = db.Column(db.Integer, default=0)
class UserAddress(db.Model):
""" 用户的地址 """
__tablename__ = 'weibo_user_addr'
id = db.Column(db.Integer, primary_key=True)
addr = db.Column(db.String(256), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('weibo_user.id'), nullable=False)
user = db.relationship('User', backref=db.backref('address', lazy=True))
@app.route('/user/<int:page>/')
def list_user(page):
""" 用户分页 """
per_page = 10 # 每一页的数据大小
# 1. 查询用户信息
user_ls = User.query
# 2. 准备分页的数据
user_page_data = user_ls.paginate(page, per_page=per_page)
return render_template('list_user.html', user_page_data=user_page_data)
list_user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户分页操作</title>
</head>
<body>
<h3>总共有{{ user_page_data.total }}用户,当前在第{{ user_page_data.page }}页用户, 总共{{ user_page_data.pages }}页</h3>
<p>
用户列表:
<ul>
{% for user in user_page_data.items %}
<li>{{ user.username }} - {{ user.password }}</li>
{% endfor %}
</ul>
{% if user_page_data.has_prev %}
<a href="{{ url_for('list_user', page=user_page_data.prev_num) }}">上一页</a>
{% endif %}
{% if user_page_data.has_next %}
<a href="{{ url_for('list_user', page=user_page_data.next_num) }}">下一页</a>
{% endif %}
</p>
</body>
</html>