再读狗书4-数据库

再读狗书4-数据库,第1张

再读狗书4-数据库 Flask-SQLAlchemy
  • Flask-SQLAlchemy 是一个 Flask 扩展,简化了在 Flask 程序中使用 SQLAlchemy 的 *** 作。SQLAlchemy 是一个很强大的关系型数据库框架,支持多种数据库后台。SQLAlchemy 提供了高层 ORM,也提供了使用数据库原生 SQL 的低层功能。

  • 常用的数据库链接

    数据库引擎URLMySQLmysql://username:password@hostname/databasePostgrespostgresql://username:password@hostname/databaseSQLite(Unix)sqlite:absolute/path/to/databaseSQLite(Windows)sqlite:///c:/absolute/path/to/database
配置数据库
import os
from flask_sqlalchemy import SQLAlchemy

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATAbase_URI'] =
 'sqlite:///' + os.path.join(basedir, 'data.sqlite')  # 配置数据库链接
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True  # 自动提交数据库的变动
db = SQLAlchemy(app)
# db对象是`SQLAlchemy`的实例,表示程序使用的数据库,同时还获得了`Flask-SQLAlchemy`提供的所有功能。
定义模型
  • 模型这个术语表示程序使用的持久化实体。在 ORM 中,模型一般是一个 Python 类,类中的属性对应数据库表中的列。Flask-SQLAlchemy 创建的数据库实例为模型提供了一个基类以及一系列辅助类和辅助函数,可用于定义模型的结构:

    class Role(db.Model):
        __tablename__ = 'roles'  # 定义表名称
        id = db.Colunm(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True)
        
        def __repr__(self):  # 实现对象返回值为其`name`属性值
            return '' % self.name
    
    class User(db.Model):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(64), unique=True, index=True)
        
        def __repr__(self):
            return '' % self.username
    
  • 常用的SQLAlchemy列类型

    类型名Python类型说明Integerint普通整数,一般是32位SmallIntegerint取值范围小的整数,一般是16位BigIntegerint 或 long不限制精度的整数Floatfloat浮点数Stringstr变长字符串Textstr变长字符串,对较长或不限长度的字符串做了优化Datedatetime.date日期DateTimedatetime.time时间Unicodeunicode变长 Unicode 字符串
  • 常用的的SQLAlchemy列选项

    选项名说明primary_key如果设为 True,这列就是表的主键unique如果设为 True,这列不允许出现重复的值index如果设为 True,为这列创建索引,提升查询效率nullable如果设为 True,这列允许使用空值;如果设为 False,这列不允许使用空值default为这列定义默认值
模型关系
  • 定义一对多关系

    # 一个角色可以有多个用户,一个用户只能有一个角色,即 角色:用户 -> 1:N
    class Role(db.Model):  # 角色模型
        # ...
        users = db.relationship('User', backref='role')
    class User(db.Model):  # 用户模型
        # ...
        role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    
  • 常用的SQLAlchemy关系选项

    选项名说明backref在关系的另一个模型中添加反向引用primaryjoin明确指定两个模型之间使用的联结条件。只在模棱两可的关系中需要指定lazy指定如何加载相关记录。可选值有 select(首次访问时按需加载)、immediate(源对象加载后就加载)、joined(加载记录,但使用联结)、subquery(立即加载,但使用子查询),noload(永不加载)和 dynamic(不加载记录,但提供加载记录的查询)uselist如果设为 Fales,不使用列表,而使用标量值order_by指定关系中记录的排序方式secondary指定多对多关系中关系表的名字secondaryjoinSQLAlchemy 无法自行决定时,指定多对多关系中的二级联结条件

    除了一对多之外,还有几种其他的关系类型。一对一关系可以用前面介绍的一对多关系表示,但调用 db.relationship() 时要把 uselist 设为 False,把“多”变成“一”。多对一关系也可使用一对多表示,对调两个表即可,或者把外键和 db.relationship() 都放在“多”这一侧。最复杂的关系类型是多对多,需要用到第三张表,这个表称为关系表。

ORM *** 作数据库
  • Flask-SQLAlchemy 根据模型类创建数据库

    >>> python hello.py shell  # 或者使用:`Python Console`。
    >>> from hello import db
    >>> db.create_all()  # 创建所有表。
    
    # 模型类变更后,需要删库重建。
    >>> db.drop_all()  # 删除所有表。
    >>> db.create_all()
    
  • 插入行数据

    >>> from hello import Role, User
    >>> admin_role = Role(name='Admin')
    >>> mod_role = Role(name='Moderator')
    >>> user_role = Role(name='User')
    >>> user_john = User(username='john', role=admin_role)
    >>> user_susan = User(username='susan', role=user_role)
    >>> user_david = User(username='david', role=user_role)
    
    # 此时这些对象只存在于Python中,还未写入数据库,因此id尚未赋值,需要入库:
    >>> db.session.add(admin_role)
    >>> db.session.add(mod_role)
    >>> db.session.add(user_role)
    >>> db.session.add(user_john)
    >>> db.session.add(user_susan)
    >>> db.session.add(user_david)
    # 或者简写:
    >>> db.session.add_all([admin_role, mod_role, user_role,
    ... user_john, user_susan, user_david])
    # 此时还需要将会话提交至数据库:
    >>> db.session.commit()
    # 此时id已赋值:
    >>> print(admin_role.id)
    1
    
    # 数据库回滚:添加到数据库会话中的所有对象都会还原到它们在数据库时的状态。
    db.session.rollback()
    
  • 修改行数据

    # 直接赋值对象即可
    >>> admin_role.name = 'Administrator'
    >>> db.session.add(admin_role)
    >>> db.session.commit()
    
  • 删除行数据

    # delete()方法,从数据库中删除"Moderator" 角色:
    >>> db.session.delete(mod_role)
    >>> db.session.commit()
    

    删除与插入和更新一样,提交数据库会话后才会执行。

  • 查询行数据

    >>> Role.query.all()
    [, ]
    >>> User.query.all()
    [, , ]
    
    # 过滤精确查找1:
    >>> User.query.filter_by(role=user_role).all()
    [, ]
    # 过滤精确查找2:
    >>> user_role = Role.query.filter_by(name='User').first()
    
    # 查看原生SQL:
    >>> str(User.query.filter_by(role=user_role))
    'SELECT users.id AS users_id, users.username AS users_username,users.role_id AS users_role_id FROM users WHERe :param_1 = users.role_id'
    
  • 常用的SQLAlchemy查询过滤器

    过滤器说明filter()把过滤器添加到原查询上,返回一个新查询filter_by()把等值过滤器添加到原查询上,返回一个新查询limit()使用指定的值限制原查询返回的结果数量,返回一个新查询offset()偏移原查询返回的结果,返回一个新查询order_by()根据指定条件对原查询结果进行排序,返回一个新查询group_by()根据指定条件对原查询结果进行分组,返回一个新查询
  • 常使用的SQLAlchemy查询执行函数

    方法说明all()以列表形式返回查询的所有结果first()返回查询的第一个结果,如果没有结果,则返回 Nonefirst_or_404()返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应get()返回指定主键对应的行,如果没有对应的行,则返回 Noneget_or_404()返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应count()返回查询结果的数量paginate()返回一个 Paginate(分页) 对象,它包含指定范围内的结果
视图函数中 *** 作数据库
@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username = form.name.data)
            db.session.add(user)
            session['known'] = False
        else:
            session['known'] = True
            session['name'] = form.name.data
            form.name.data = ''
            return redirect(url_for('index'))
        return render_template('index.html',form = form, 
                               name = session.get('name'),
       						  	known = session.get('known', False))
Flask-script配置命令行选项
  • Flask 的开发 Web 服务器支持很多启动设置选项,但只能在脚本中作为参数传给 app.run()函数。这种方式并不十分方便,传递设置选项的理想方式是使用命令行参数。

  • 配置Flask-script

    from flask_script import Manager
    manager = Manager(app)
    # ...
    if __name__ == '__main__':
     manager.run()
    
  • shell运行 hello.py

    >>> python hello.py
    usage: hello.py [-h] {shell,runserver} ...
    positional arguments:
    {shell,runserver}
    shell  # 在 Flask 应用上下文中运行 Python shell
    runserver  # 运行 Flask 开发服务器:app.run()
    optional arguments:
    -h, --help 显示帮助信息并退出
    

    顾名思义,runserver 命令用来启动 Web 服务器:python hello.py runserver (类似Django)

Flask-script集成Python shell
  • 每次启动 shell 会话都要导入数据库实例和模型,这真是份枯燥的工作。为了避免一直重复导入,我们可以做些配置,让 Flask-script 的 shell 命令自动导入特定的对象。

    from flask.ext.script import Shell
    def make_shell_context():
        return dict(app=app, db=db, User=User, Role=Role)
    manager.add_command("shell", Shell(make_context=make_shell_context))
    

    make_shell_context() 函数注册了程序、数据库实例以及模型,因此这些对象能直接导入 shell:

  • shell中运行

    >>> python hello.py shell
    >>> app
    
    >>> db
    
    >>> User
    
    
Flask-Migrate实现数据库迁移
  • 配置Flask-Migrate

    from flask_migrate import Migrate, MigrateCommand
    # ...
    migrate = Migrate(app, db)  # 绑定app对象和数据库对象。
    manager.add_command('db', MigrateCommand)
    
  • 迁移命令

    # 初始化,这个命令会创建 migrations 文件夹,所有迁移脚本都存放其中。
    >>> python hello.py db init  
    # 创建迁移脚本
    >>> python hello.py db migrate -m "initial migration"
    # 迁移入库
    >>> python hello.py db upgrade
    

    对第一个迁移来说,其作用和调用 db.create_all() 方法一样。但在后续的迁移中,upgrade 命令能把改动应用到数据库中,且不影响其中保存的数据。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/zaji/4003181.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-10-22
下一篇2022-10-22

发表评论

登录后才能评论

评论列表(0条)

    保存