
1. 模型Model
1.1 概述
1. Flask模型使用
2. 数据迁移
3. 模型常用的字段类型和常用约束
4. 模型单表操作
5. 创建User表,字段:id,name, passwd, age1. 实现注册功能2. 实现登录功能
1.11 Flask模型
Flask默认并没有提供任何数据库操作的API
我们可以选择任何适合自己项目的数据库来使用
Flask中可以自己的选择用原生语句实现功能,也可以选择ORM(SQLAlchemy,MongoEngine)原生SQL缺点代码利用率低,条件复杂代码语句越长,有很多相似语句一些SQL是在业务逻辑中拼出来的,修改需要了解业务逻辑直接写SQL容易忽视SQL问题
1.12 ORM
Flask通过Model操作数据库,不管你数据库的类型是MySql或者Sqlite,Flask自动帮你生成相应数据库类型的SQL语句,所以不需要关注SQL语句和类型,对数据的操作Flask帮我们自动完成。只要会写Model就可以了。Flask使用对象关系映射(Object Relational Mapping,简称ORM)框架去操控数据库。ORM(Object Relational Mapping)对象关系映射,是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。将对对象的操作转换为原生SQL
优点易用性,可以有效减少重复SQL性能损耗少设计灵活,可以轻松实现复杂查询移植性好
Flask的ORM
Flask使用Python自带的ORM:SQLAlchemy针对于Flask的支持,安装插件 flask-sqlalchemypip install flask-sqlalchemy
连接SQLite
SQLite连接的URI:DB_URI = sqlite:///sqlite3.db
连接MySQL
USERNAME='root'
PASSWORD='root'
HOSTNAME = 'localhost'
PORT='3306'
DATABASE='HelloFlask'格式: mysql+pymysql://USERNAME:PASSWORD@HOSTNAME:PORT/DATABASE
DB_URI='mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE
)
在Flask中使用ORM
连接数据库需要指定配置app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False SQLite数据库连接不需要额外驱动,也不需要用户名和密码
db = SQLAlchemy()
db.init_app(app)
1.21 创建模型
class Person(db.Model):__tablename__='person'id = db.Column(db.Integer,primary_key=True)name = db.Column(db.String(16),unique=True)字段类型Integer FloatString常用约束primary_keyautoincrementuniquedefault数据简单操作创建数据库,表db.create_all()删除表db.drop_all()在事务中处理,数据插入db.session.add(object) db.session.commit()获取所有数据Person.query.all()
1.2 数据迁移
Flask数据迁移详细步骤
安装pip install flask-migrate初始化使用app和db进行migrate对象初始化from flask_migrate import Migratemigrate = Migrate()migrate.init_app(app=app, db=db)数据迁移命令:在cmd或Terminal先进入项目目录:然后输入命令:flask db init 创建迁移文件夹migrates, 只调用一次flask db migrate 生成迁移文件flask db upgrade 执行迁移文件中的升级flask db downgrade 执行迁移文件中的降级
2. 模型操作
2.1 创建模型
class Person(db.Model):__tablename__ = 'person'id = db.Column(db.Integer, primary_key=True, autoincrement=True)name = db.Column(db.String(20), unique=True)age = db.Column(db.Integer, default=1)
2.11 字段类型
类型名 |
Python类型 |
说 明 |
Integer |
int |
普通整数, 一般是 32 位 |
SmallInteger |
int |
取值范围小的整数,一般是 16 位 |
BigInteger |
int 或 long |
不限制精度的整数 |
Float |
float |
浮点数 |
Numeric |
decimal.Decimal |
定点数 |
String |
str |
变长字符串 |
Text |
str |
长字符串,对较长或不限长度的字符串做了优化 |
Unicode |
unicode |
变长 Unicode 字符串 |
UnicodeText |
unicode |
变长 Unicode 字符串,对较长或不限长度的字符串做了优化 |
Boolean |
bool |
布尔值 |
Date |
datetime.date |
日期 |
Time |
datetime.time |
时间 |
DateTime |
datetime.datetime |
日期和时间 |
Interval |
datetime.timedelta |
时间间隔 |
LargeBinary |
str |
二进制文件 |
2.12 常用约束
选项名 |
说 明 |
primary_key |
如果设为 True ,这列就是表的主键 |
unique |
如果设为 True ,这列不允许出现重复的值 |
index |
如果设为 True ,为这列创建索引,提升查询效率 |
nullable |
如果设为 True ,这列允许使用空值;如果设为 False ,这列不允许使用空值 |
default |
为这列定义默认值 |
2.2 模型操作
2.21 单表操作
增加数据a. 一次增加一条数据:p = Person() p.name = '小明' p.age = 22try:db.session.add(p)db.session.commit()except:db.session.rollback()db.session.flush()b. 一次添加多条数据persons = []for i in range(10,30):p = Person()p.name = '宝强' + str(i)p.age = ipersons.append(p)db.session.add_all(persons)db.session.commit()删除数据p = Person.query.first() db.session.delete(p)db.session.commit()修改数据p = Person.query.first()p.age = 100db.session.commit()查询数据过滤器filter() 把过滤器添加到原查询上,返回一个新查询filter_by() 把等值过滤器添加到原查询上,返回一个新查询limit() 使用指定的值限制原查询返回的结果数量,返回一个新查询 offset() 偏移原查询返回的结果,返回一个新查询order_by() 根据指定条件对原查询结果进行排序,返回一个新查询group_by() 根据指定条件对原查询结果进行分组,返回一个新查询常用查询all() 以列表形式返回查询的所有结果,返回列表first() 返回查询的第一个结果,如果没有结果,则返回 Nonefirst_or_404() 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应get() 返回指定主键对应的行,如果没有对应的行,则返回 Noneget_or_404() 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应count() 返回查询结果的数量paginate() 返回一个 Paginate 对象,它包含指定范围内的结果查询属性containsstartswith endswithin_ __gt____ge____lt____le__逻辑运算与 and_filter(and_(条件),条件…)或 or_filter(or_(条件),条件…)非 not_filter(not_(条件),条件…)示例: 查询:persons = Person.query.all() persons = Person.query.filter(Person.age>22)persons = Person.query.filter(Person.age==22) persons = Person.query.filter_by(age=22) persons = Person.query.filter(Person.age.__lt__(22)) persons = Person.query.filter(Person.age.__le__(22)) persons = Person.query.filter(Person.age.__gt__(22)) persons = Person.query.filter(Person.age.__ge__(22)) persons = Person.query.filter(Person.age.startswith('宝')) persons = Person.query.filter(Person.age.endswith('宝')) persons = Person.query.filter(Person.age.contains('宝')) persons = Person.query.filter(Person.age.in_([11,12,22])) persons = Person.query.filter(Person.age>=20, Person.age<30) persons = Person.query.filter(and_(Person.age>=20, Person.age<30)) persons = Person.query.filter(or_(Person.age>=30, Person.age<20)) persons = Person.query.filter(not_(Person.age<30)) 排序:persons = Person.query.order_by('age') persons = Person.query.order_by(desc('age')) 分页:persons = Person.query.limit(5) persons = Person.query.offset(5) page = int(request.args.get('page'))per_page = int(request.args.get('per_page'))persons = Person.query.offset((page-1) * per_page).limit(per_page)persons = Person.query.paginate(page=page, per_page=per_page, error_out=False).itemspaginate对象的属性:items:返回当前页的内容列表has_next:是否还有下一页has_prev:是否还有上一页next(error_out=False):返回下一页的Pagination对象prev(error_out=False):返回上一页的Pagination对象page:当前页的页码(从1开始)pages:总页数per_page:每页显示的数量prev_num:上一页页码数next_num:下一页页码数total:查询返回的记录总数