> 文章列表 > Flask模型基础--03

Flask模型基础--03

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:查询返回的记录总数