Flask模型基础--03

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# 配置URL
DB_URI='mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE
)
在Flask中使用ORM
连接数据库需要指定配置app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI # 配置连接数据库路径DB_URIapp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 禁止对象追踪修改SQLite数据库连接不需要额外驱动,也不需要用户名和密码# 在Flask项目中使用
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)# filter功能比filter_by强大persons = Person.query.filter(Person.age==22) # filter(类.属性==值)persons = Person.query.filter_by(age=22) # filter_by(属性=值)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])) # in_persons = Person.query.filter(Person.age>=20, Person.age<30) # and_persons = Person.query.filter(and_(Person.age>=20, Person.age<30)) # and_persons = Person.query.filter(or_(Person.age>=30, Person.age<20)) # or_persons = Person.query.filter(not_(Person.age<30)) # not_排序:persons = Person.query.order_by('age') # 升序persons = Person.query.order_by(desc('age')) # 降序分页:persons = Person.query.limit(5) # 取前5个persons = Person.query.offset(5) # 跳过前5个# 获取页码page和每页数量numpage = int(request.args.get('page'))per_page = int(request.args.get('per_page'))# 手动做分页persons = Person.query.offset((page-1) * per_page).limit(per_page)# 使用paginate做分页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:查询返回的记录总数


