第四课 Flask数据模型Model

Flask 第四课Flask数据模型Model

tags:

  • Flask
  • 2019千锋教育

categories:

  • flask
  • model
  • 数据模型
  • flask-caching

文章目录

  • Flask 第四课Flask数据模型Model
    • 第一节 flask的模型
    • 第二节 数据库连接
      • 1. mysql连接
      • 2. Sqlite连接
    • 第三节 ORM字段类型
      • 1. 继承自己的定义的模型类
      • 2. 项目中数据库优化
    • 第四节 ORM数据操作
      • 1. 添加数据
      • 2. 查询数据
        • 2.1 普通查询
        • 2.2 外键关联
        • 2.3 逻辑运算
      • 3. 删除修改数据
    • 第五节 缓存查询flask-caching

第一节 flask的模型

Flask默认并没有提供任何数据库操作的API,我们可以选择任何适合自己项目的数据库来使用Flask中可以自己的选择数据,用原生语句实现功能,也可以选择ORM ( SQLAIchemy,MongoEngine)

  1. 原生SQL缺点
    • 代码利用率低,条件复杂代码语句越长,有很多相似语句
    • 一些SQL是在业务逻辑中拼出来的,修改需要了解业务逻辑
    • 直接写SQL容易忽视SQL问题
  2. ORM将对对象的操作转换为原生SQL优点
    • 性能损耗少
    • 设计灵活,可以轻松实现复杂查询
    • 移植性好
      python的ORM (SQLAIchemy)针对于Flask的支持: pip install flask-sqlalchemy -i https://pypi.douban.com/simple

第二节 数据库连接

1. mysql连接

dialect+driver://usermame:password@host:port/database
dialect数据库实现 driver数据库的驱动
例子:
app.config[‘SQLALCHEMY_DATABASE_URI’]=‘mysql+pymysql://root:123456@127.0.0.1:3306/flask_test’

2. Sqlite连接

app.config[‘SQLALCHEMY_ DATABASE_ URI’]= DB URI
aDD.configI’SQLALCHEMY_ TRAKE_ MODIFICATIONS’]=False 禁止对象追踪修改
SQLite数据库连接不需要额外驱动,也不需要用户名和密码
SQLite连接的URI:DB_ URI = sglite:///sqlite3.db

第三节 ORM字段类型

常用字段:SmalllntegerBigIntegerFloat
NumericStringTextUnicode
Unicode TextBooleanDateTime
DateTimeIntervalLargeBinary
  1. 初始化:python manage.py db init
  2. 升级:python manage.py db upgrade
  3. 降级回退:python manage.py db downgrade
  4. 生成迁移文件:python manage.py db migrate
  5. 生成迁移数据库前要看一下模型类,有没有注册到views文件中。from App.models import models, User
  6. models.create_all()创建表, models.drop_all()删除表
  7. 常用约束
    • primary key autoincrement unique index
    • nullable default ForeignKey()

1. 继承自己的定义的模型类

  1. 表名: _tablename
  2. 模型继承
    • 默认继承并不会报错,它会将多个模型的数据映射到一张表中,导致数据混乱,不能满足基本使用
    • 抽象的模型是不会在数据库中产性映射的: abstract =True
  3. 文档
    • flask-sqlalchemy
    • sqlalchemy
  4. 实际案例
# 会员数据模型
# 修改完模型后:python manage.py db migrate
# 修改完模型后:python manage.py db upgrade
class User(models.Model):# 修改表名__tablename__ = 'UserModel'id = models.Column(models.Integer, primary_key=True)  # 编号username = models.Column(models.String(100), unique=True)  # 昵称password = models.Column(models.String(100))  # 密码desc = models.Column(models.String(128), nullable=True)
  1. 如果继承类,只生成一张Animal表。不生成dog和cat表。dog和cat的字段集成在Animal表中。如果对cat和dog表添加数据。一些字段会默认赋值,数据就混乱了。解决方法见6.
# 如果继承类,只生成一张Animal表。不生成dog和cat表。dog和cat的字段集成在Animal表中。
class Animal(models.Model):id = models.Column(models.Integer, primary_key=True)u_name = models.Column(models.String(100), unique=True)class Dog(Animal):d_tags = models.Column(models.Integer, default=4)class Cat(Animal):c_tags = models.Column(models.String(32), default='fish')
  1. 降级表,把Animal变成抽象表。然后重新生成表结构。发现生成dog表和cat表
	# 降级表:1. python manage.py db downgrade# 降级表:2. 删除对应的表py文件# 降级表:3. python manage.py db migrate# 降级表:4. python manage.py db upgrade
class Animal(models.Model):# Django 中可以把类变成抽象类处理,这里也把类变为抽象类__abstract__= Trueid = models.Column(models.Integer, primary_key=True)u_name = models.Column(models.String(100), unique=True)class Dog(Animal):d_tags = models.Column(models.Integer, default=4)class Cat(Animal):c_tags = models.Column(models.String(32), default='fish')

2. 项目中数据库优化

  1. 怎么优化
  2. 连接多少次(mysql默认最大连接数目是100个)
  3. 其实无论是Django还是flask都是有数据库连接池的
    • SQLALCHEMY_POOL_SIZE (连接池大小默认5个)
    • SQLALCHEMY_POOL_TIMEOUT 超时时间
    • SQLALCHEMY_POOL_RECYCLE (回收时间默认两小时)

第四节 ORM数据操作

1. 添加数据

  1. 下面导入的models = SQLAlchemy(),也常常把models变为db。
  2. add()添加,add_all()添加多条数据
# 插入单条数据
@blue.route('/adduser')
def adduser():user = User()user.username = 'root'user.password = '123456'models.session.add(user)models.session.commit()print(models.session)print(type(models.session))return '添加成功'@blue.route('/addusers')
def addusers():users = []for i in range(5):user = User()user.username = 'bili%d'% iuser.password = '123456'users.append(user)models.session.add_all(users)models.session.commit()return '添加多条成功'

2. 查询数据

2.1 普通查询

  1. 查询数据结果集
  2. 语法: 类名.guery.xxx
  3. 获取单个对象
    • first() 或 first_or_404()
    • get() 或 get_or_404() 只支持id不支持其他字段
  4. 获取结果集
    • all() 比较特殊。返回一个列表
    • filter(类名.属性名.运算符(xxx’)) 返回BaseQuery对象。
    • filter(类名.属性数学运算符值)
      • 魔术方法:eq lt gt ge le
      • 操运算作符: == > <
      • contains startswith endswith in_ like
      • filter_by() offset()偏移 limit() order_ by() paginate()
      • offset和limit不区分顺序,怎么写都按offset先跳过在限制
      • order_by必须在offset和limit之前
    • BaseQuery对象后可以继续加条件,但是list后不可以
    • 所以如果在flask-sqlalchemy使用list, 要放在最后。
@blue.route('/getcat')
def getcat():#cats = Cat.query.filter(Cat.id.__gt__(2)).all()#cats = Cat.query.filter(Cat.id == (5)).all()#cats = Cat.query.filter(Cat.u_name.contains('猫')).all()#cats = Cat.query.filter(Cat.id.in_([1, 5, 6])).all()#cats = Cat.query.order_by(Cat.id.desc()).all()# offset和limit不区分顺序,怎么写都按offset先跳过在限制#cats = Cat.query.offset(1).limit(2).all()#cats = Cat.query.order_by("id").offset(1).limit(2).all()# BaseQuery的__str__方法, 会把它转为sql语句#cats = Cat.query.order_by("id").offset(1).limit(2).all()cats = Cat.query.filter_by(id=5).all()print(cats)print(type(cats))#render_template('cat.html', cat=cats)return "成功"@blue.route('/getdog')
def getdog():from flask import requestpage = request.args.get('page', 1, type=int)per_page = request.args.get('per_page', 4, type=int)dogs = Dog.query.offset(per_page * (page - 1)).limit(per_page)print(dogs)print(type(dogs))return "成功"@blue.route('/getdogwithpage/')
def getdogwithpage():#dogs = Dog.query.paginate().items#render_template('dog.html', dog=cdogs)# 传分页器过去而不是数据过去pagination = Dog.query.paginate()render_template('dog.html', pagination=pagination)

2.2 外键关联

  1. filter_by 通常用在级联数据查询上。直接手动获取如下
# 创建模型
class Customer(models.Model):id = models.Column(models.Integer, primary_key=True, autoincrement=True)c_name = models.Column(models.String(16))class Address(models.Model):id = models.Column(models.Integer, primary_key=True, autoincrement=True)a_position = models.Column(models.String(20))a_customer_id = models.Column(models.Integer, models.ForeignKey(Customer.id))
@blue.route('/addcustomer')
def add_customer():import randomcostumer = Customer()costumer.c_name = '剁手党%d' % random.randrange(1000)models.session.add(costumer)models.session.commit()return "添加成功"@blue.route('/addaddress')
def add_address():import randomaddress = Address()address.a_position = '上海%d' % random.randrange(1000)address.a_customer_id = Customer.query.order_by(Customer.id.desc()).first().idmodels.session.add(address)models.session.commit()return "添加成功"@blue.route('/get_customer')
def get_customer():# 获取id=1的地址的客户address = Address.query.get_or_404(1)customer = Customer.query.get(address.a_customer_id)return customer.c_name@blue.route('/get_addr/')
def get_addr():# 客户1的所有地址customer = Customer.query.get(1)addresses = Address.query.filter_by(a_customer_id=customer.id)for addr in addresses:print(addr.a_position)return '获取成功'
  1. 使用关系Relationships获取: relationship 通过customer直接获取得到一个列表(address = models.relationship(‘Address’, backref=‘customer’, lazy=True))
class Customer(models.Model):id = models.Column(models.Integer, primary_key=True, autoincrement=True)c_name = models.Column(models.String(16))address = models.relationship('Address', backref='customer', lazy=True)class Address(models.Model):id = models.Column(models.Integer, primary_key=True, autoincrement=True)a_position = models.Column(models.String(20))a_customer_id = models.Column(models.Integer, models.ForeignKey(Customer.id))
@blue.route('/get_addr/')
def get_addr():# 客户1的所有地址customer = Customer.query.get(1)#addresses = Address.query.filter_by(a_customer_id=customer.id)# relationship 通过customer直接获取得到一个列表addresses = customer.addressprint(addresses)for addr in addresses:print(addr.a_position)return '获取成功'
  1. 关系
    • 一对一:ForeignKey+Unique
    • 一对多:ForeignKey
    • M*N多对多:额外关系表 ForeignKey+ForeignKey
    • 一对一多对多 项目中不建议使用。自己手动维护官网也有生成中间表的写法。

2.3 逻辑运算

  1. 与 and_ filter(and_ (条件),条件…)
  2. 或 or_ filter(or_ (条件),条件…)
  3. 非 not_ filter(not_ (条件),条件…)
@blue.route('/get_addrwithconn/')
def get_addrwithconn():from sqlalchemy import and_,or_,not_#addresses = Address.query.filter(Address.a_customer_id.__eq__(1)).filter(Address.a_position.endswith('5'))# 逻辑符号and_#addresses = Address.query.filter(and_(Address.a_customer_id.__eq__(1), Address.a_position.endswith('5')))# 逻辑符号or_#addresses = Address.query.filter(or_(Address.a_customer_id.__eq__(1), Address.a_position.endswith('5')))# 逻辑符号not_#addresses = Address.query.filter(not_(Address.a_customer_id.__eq__(1)))addresses = Address.query.filter(not_(or_(Address.a_customer_id.__eq__(1), Address.a_position.endswith('5'))))print(addresses)for addr in addresses:print(addr.a_position)#return render_template('Address.hmtl', addresses=addresses)return '获取成功'

3. 删除修改数据

  1. 删除数据。delete
  2. models.session.delete() models.session.commit()
  3. 修改数据。add重新保存
@blue.route('/deleteuser')
def deleteuser():user = User.query.first()models.session.delete(user)models.session.commit()return '删除数据成功'@blue.route('/updateuser')
def updateuser():user = User.query.first()user.username = 'root'# 修改数据后重新保存models.session.add(user)models.session.commit()return '修改数据成功'

第五节 缓存查询flask-caching

  1. 低版本的flask用flask-cache
  2. 高版本的flask用flask-caching(功能一样,都是做数据缓存的。重复请求从缓存中读数据).说明文档可能被墙。
  3. pip install flask-caching
  4. 导包from flask_caching import Cache
  5. 配置:可以配置null, simple, redis, memcached,filesystem
cache = Cache(config={"CACHE_TYPE": "simple"
})
  1. 注册cache.init_app(app=app)
  2. 使用如下
@blue.route('/get_addrwithconn/')
@cache.cached(timeout=60)
def get_addrwithconn():from sqlalchemy import not_,  or_addresses = Address.query.filter(not_(or_(Address.a_customer_id.__eq__(1), Address.a_position.endswith('5'))))print(addresses)print('从数据库中查询')for addr in addresses:print(addr.a_position)#return render_template('Address.hmtl', addresses=addresses)return '获取成功'


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部