Flask 中的MTV架构之Models

Flask 中的MTV架构之Models

1、Models(数据模型)
1.1 flask-sqlalchemy(数据库)

​ 说明:提供了大多数关系型数据库的支持,而且提供了ORM

# 安装:
pip install flask-sqlalchemy
1.2使用

​ a. 数据库地址/链接

#MySQL,必须事先创建数据库
mysql+pymysql://username:password@host/database
#SQLite,系统会自动创建数据库
sqlite:///path/to/dbfile
app.config['SQLALCHEMY_DATABASE_URI'] = database_uri

​ b.基本配置

# 数据改变后自动提交
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
# 数据变化的自动警告关闭
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

​ c.创建对象 db = SQLAlchemy(app)
d.范例

   # 导入类库
   from flask_sqlalchemy import SQLAlchemy

   # 配置数据库链接地址
   base_dir = os.path.abspath(os.path.dirname(__file__))
   database_uri = 'sqlite:///' + os.path.join(base_dir, 'data.sqlite')
   app.config['SQLALCHEMY_DATABASE_URI'] = database_uri

   # 是否追踪数据的改变,发出警告,占用额外内容,不需要时可以禁用
   app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

   # 创建对象
   db = SQLAlchemy(app)
1.3 定义数据模型
#自动生成表名规则:驼峰转【小写字母+下划线】
class User(db.Model):
# 不指定表名,默认会将大驼峰转换为:小写+下划线,
#如:类名UserModel => 表名user_model
# 指定表名,使用__tablename__属性
tablename = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, unique=True)

​ 范例

   # 定义数据模型类
   class User(db.Model):
       __tablename__ = 'users'
       id = db.Column(db.Integer, primary_key=True)
       username = db.Column(db.String(32), unique=True)
       email = db.Column(db.String(64), unique=True)
1.4 建表和删除表

db.create_all()
db.drop_all()
范例

   # 创建表,若是sqlite没有数据库时会自动创建,
   #若是MySQL没有数据库会报错
   @app.route('/create/')
   def create():
       db.drop_all()
       # 若表已经存在,则不会再次创建,手动删除后才可再次创建
       db.create_all()
       return '数据表已创建'

   # 删除表
   @app.route('/drop/')
   def drop():
       db.drop_all()
       return '数据表已删除'
1.5数据迁移

​ @manager.command装饰命令函数
python manage.py createall

   # 创建表:python manage.py createall
   @manager.command
   def createall():
       db.drop_all()
       db.create_all()
       return '数据表已创建'

python manage.py dropall

# 删除表:python manage.py dropall 
@manager.command 
def dropall(): 
    if prompt_bool('确定要删库吗?'): 
        db.drop_all() 
        return '数据表已删除' 
    return '还是再考虑一下吧'

​ 使用migrate来执行数据迁移

pip install flask_migrate
migrate = Migrate(app, db)
from flask_migrate import Migrate, MigrateCommand
manager.add_command('db', MigrateCommand)
#1、初始化数据库迁移的仓库,执行一次就行了
python manage.py db init
#2.创建迁移脚本,会根据数据模型与数据表的差异生成SQL语句
python manage.py db migrate
#3.执行迁移,就是执行上面生成的SQL语句
python manage.py db upgrade

1.6 CRUD(增删改查)

​ a.插入Create

  dandan = User(username='dandan', email='dandan@163.com')
  db.session.add(dandan)

​ o范例

@app.route('/insert/')
def insert():
   # 创建数据模型
   dandan = User(username='dandan', email='dandan@163.com')
   # 添加到数据库
   db.session.add(dandan)

   # 添加多条数据
   #niannian = User(username='niannian', email='niannian@163.com')
   #chaochao = User(username='chaochao', email='chaochao@163.com')
   #erchao = User(username='erchao', email='erchao@163.com')
   #db.session.add_all([niannian, chaochao, erchao])

   # 提交操作(执行前面的SQL语句),
   #除非设置SQLALCHEMY_COMMIT_ON_TEARDOWN
   #db.session.commit()
   return '数据已添加'

​ b.查询Retrieve
查询全部
users = User.query.all()
条件查询
id查询
u = User.query.get(uid) # 根据主键查询,没有返回None
u = User.query.get_or_404(8)
o范例

   @app.route('/select/<uid>')
   def select(uid):
       # 根据主键查询,没有返回None
       u = User.query.get(uid)
       if u:
           return u.username
       return '查无此人'

​ 条件查询

#指定过滤条件(只能是等值条件)
u = User.query.filter_by(username='dandan').first()
u = User.query.filter(User.id == 2).first()
u = User.query.filter(User.id > 2).first()
u = User.query.filter(User.id > 8).first_or_404()

​ 统计数量
total = User.query.count()
分页查询
pagination = Posts.query.paginate(2, per_page=5, error_out=False)
posts = pagination.items
排序
posts = Posts.query.order_by(Posts.timestamp.desc()).all()
执行分组查询

ret = db.session.query(User.age,func.count(User.id)).group_by(User.age).all()
 #结果类似ret2= [(0, 1), (1, 2), (2, 2), (3, 1)]

​ 常用的func.xxx
count()
sum()
max()
min()
avg()

limit
offset

​ c.更新Update

  u = User.query.get(uid)
  u.email = 'yyy@163.com'
  # 更新没有单独的函数,当添加的对象有ID时认为是更新
  db.session.add(u)

​ d.删除Delete
u = User.query.get(uid)
db.session.delete(u)

1.6数据库设计

​ a.常见类型

Integer | int | 32位
SmallInteger | int | 16位
BigInteger | int/long | 不受限制的整数
Float | float | 浮点数
String | str | 变长字符串
Text | str | 变长字符串,做了优化
Boolean | bool | 布尔值
DateTime | datetime.datetime | 日期时间

​ b.常见约束

 primary_key | 是否作为主键索引,默认为False
 autoincrement | 自增长约束,默认False
 unique | 是否作为唯一索引,默认为False
 nullable | 是否可以为空,默认为True
 default | 设置默认值
 index | 索引约束,默认False
 
 
   索引是对数据库表中一列或多列的值进行排序的一种结构,
索引是对数据库表中一个或多个列(例如,employee 表的姓名 (name)列)的值
进行排序的结构。
如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,
索引有助于更快地获取信息。
例如这样一个查询:select * from table1 where id=10000。
如果没有索引,必须遍历整个表,直到ID等于10000的这一行被找到为止;
有了索引之后(必须是在ID这一列上建立的索引),即可在索引中查找。
由于索引是经过某种算法优化过的,因而查找次数要少的多。
可见,索引是用来定位的
1.7 拓展

​ a.执行原生SQL语句

 ret = db.session.execute('select * from user').fetchall()

​ b.懒加载取值lazy=?
True/select
懒加载
只有去访问关联方时才会临时执行查询
查询一张孤立的表
应用场景:数据量大,或者关联方查询频率低
False/joined
勤快加载
无论是否访问关联方,都会事先查询好
使用join做联合查询
应用场景:数据量小,或者关联方查询频率很高
subquery
勤快加载
无论是否访问关联方,都会事先查询好
使用独立的子查询(多对多时慎用)
应用场景:数据量小,或者关联方查询频率很高
dynamic
只能应用于一对多的一方

【后记】:如果文章对您有帮助,打赏下呗。微信 1257309054,欢迎交流学习*_*
微信
在这里插入图片描述
支付宝
在这里插入图片描述

posted @ 2018-06-29 14:50  轻松学编程  阅读(297)  评论(0编辑  收藏  举报