flask学习笔记(-数据库)

Python 数据库框架

大多数的数据库引擎都有对应的 Python 包,包括开源包和商业包。Flask 并不限制你使用何种类型的数据库包,因此可以根据自己的喜好选择使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。

如果这些都无法满足需求,还有一些数据库抽象层代码包供选择,例如SQLAlchemyMongoEngine。你可以使用这些抽象包直接处理高等级的 Python 对象,而不用处理如表、文档或查询语言此类的数据库实体。

选择数据库框架的因素:

  • 易用性。抽象层,也称为对象关系映 射(Object-Relational Mapper,ORM) 或 对 象 文 档 映 射(Object-Document Mapper,ODM),在用户不知觉的情况下把高层的面向对象操作转换成低层的数据库指令。
  • 性能。ORM 和 ODM 把对象业务转换成数据库业务会有一定的损耗。真正的关键点在于如何选择一个能直接操作低层数据库的抽象层,以防特定的操作需要直接使用数据库原生指令优化。
  • 可移植性。必须考虑其是否能在你的开发平台和生产平台中使用。
  • Flask集成度

Flask-SQLAlchemy 管理数据库

  • 安装

pip install flask-sqlalchemy

使用URL制定数据库

数据库引擎URL
MySQLmysql://username:password@hostname/database
Postgrespostgresql://username:password@hostname/database
SQLite(Unix)sqlite:absolute/path/to/database
SQLite(Windows)sqlite:///c:/absolute/path/to/database

SQLite 数 据 库 不 需 要 使 用 服 务 器, 因 此 不 用 指 定 hostname 、 username 和 password 。URL 中的 database 是硬盘上文件的文件名。

  • 配置 
    程序使用的数据库 URL 必须保存到 Flask 配置对象的 SQLALCHEMY_DATABASE_URI 键中

配置对象中还有一个很有用的选项,即 SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为 True时,每次请求结束后都会自动提交数据库中的变动

from flask.ext.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)

 

 

  • 定义模型
    class Role(db.Model):
        #__tablename__ 定义在数据库中使用的表名,如果没有定义 __tablename__ ,
        #SQLAlchemy 会使用一个默认名字
        __tablename__ = 'roles'
        #primary_key如果设为 True ,这列就是表的主键
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True)
        def __repr__(self):
            return '<Role % r>' % 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 '<User % r>' % self.username
    

     

     

    最常用的SQLAlchemy列类型

    类型名Python类型说 明
    Integerint普通整数,一般是 32 位
    SmallIntegerint取值范围小的整数,一般是 16 位
    BigIntegerint 或 long不限制精度的整数
    Floatfloat浮点数
    Numericdecimal.Decimal定点数
    Stringstr变长字符串
    Textstr变长字符串,对较长或不限长度的字符串做了优化
    Unicodeunicode变长 Unicode 字符串
    UnicodeTextunicode变长 Unicode 字符串,对较长或不限长度的字符串做了优化
    Booleanbool布尔值
    Datedatetime.date日期
    Timedatetime.time时间
    DateTimedatetime.datetime日期和时间
    Intervaldatetime.timedelta时间间隔
    Enumstr一组字符串
    PickleType任何 Python 对象自动使用 Pickle 序列化
    LargeBinarystr二进制文件

    最常使用的SQLAlchemy列选项

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

 

关系表达

关系型数据库使用关系把不同表中的行联系起来。

  • 一对多
    class Role(db.Model):
        #添加到 Role 模型中的 users 属性代表这个关系的面向对象视角。
        #对于一个 Role 类的实例,其 users 属性将返回与角色相关联的用户组成的列表。
        #db.relationship() 的第一个参数表,如果模型类尚未定义,可使用字符串形式指定。
        #db.relationship() 中的 backref 参数向 User 模型中添加一个 role 属性,从而定义反向关系。
        #这一属性可替代 role_id 访问 Role 模型,此时获取的是模型对象
        users = db.relationship('User', backref='role')
    class User(db.Model):
        #关系使用 users 表中的外键连接了两行。
        #添加到 User 模型中的 role_id 列被定义为外键,就是这个外键建立起了关系。
        #传给 db.ForeignKey() 的参数 'roles.id' 表明,这列的值是 roles 表中行的 id 值。
        role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

     

    db.relationship() 都能自行找到关系中的外键,但有时却无法决定把哪一列作为外键。如果 User 模型中有两个或以上的列定义为 Role 模型的外键,SQLAlchemy 就不知道该使用哪列。如果无法决定外键,你就要为 db.relationship() 提供额外参数,从而确定所用外键

     

  • 常用的SQLAlchemy关系选项

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

  • 多对多

    tags = db.Table('tags',
        db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
        db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
    )
    
    class Page(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        tags = db.relationship('Tag', secondary=tags,
            backref=db.backref('pages', lazy='dynamic'))
    
    class Tag(db.Model):
        id = db.Column(db.Integer, primary_key=True)

     

     

    查询行

  • 查询全部。Role.query.all()
  • 条件查询(使用过滤器)。User.query.filter_by(role=user_role).all()
 

#filter_by() 等过滤器在 query 对象上调用,返回一个更精确的 query 对象。
user_role = Role.query.filter_by(name='User').first()

 

  • 常用过滤器

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

最常使用的SQLAlchemy查询执行函数

方 法说 明
all()以列表形式返回查询的所有结果
first()返回查询的第一个结果,如果没有结果,则返回 None
first_or_404()返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应
get()返回指定主键对应的行,如果没有对应的行,则返回 None
get_or_404()返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应
count()返回查询结果的数量
paginate()返回一个 Paginate 对象,它包含指定范围内的结果
  • 关系查询

    #执行 user_role.users 表达式时,隐含的查询会调用 all() 返回一个用户列表。 
    #query 对象是隐藏的,因此无法指定更精确的查询过滤器。
    users = user_role.users
    
    #修改了关系的设置,加入了 lazy = 'dynamic' 参数,从而禁止自动执行查询
    class Role(db.Model):
    users = db.relationship('User', backref='role', lazy='dynamic')
    
    #顺序排列
    user_role.users.order_by(User.username).all()
    
     

    集成 Python 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

    使用 Flask-Migrate 实现数据库迁移

    创建迁移仓库

    pip install flask-migrate
     

    配置

    from flask.ext.migrate import Migrate, MigrateCommand
    # ...
    migrate = Migrate(app, db)
    manager.add_command('db', MigrateCommand)

     

     

    在维护数据库迁移之前,要使用 init 子命令创建迁移仓库

  • python hello.py db init

    创建迁移脚本

     

    python hello.py db migrate -m "initial migration"

     

    更新数据库

 

python hello.py db upgrade

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32是一款非常流行的嵌入式微控制器系列,它具有强大的性能和丰富的外设资源。在学习STM32时,掌握如何进行Flash读写是非常重要的。 Flash是一种非易失性存储器,可以用来存储程序代码和数据。在STM32中,Flash存储器通常用来存储应用程序代码。下面是一个简单的Flash读写程序的示例: 1.首先,我们需要包含适用于所使用的STM32型号的头文件。例如,对于STM32F4系列,我们需要包含"stm32f4xx.h"。 2.然后,我们需要定义一个指向Flash存储器的指针变量。例如,可以使用如下代码:`uint32_t* flash_address = (uint32_t*)0x08000000;`其中0x08000000是Flash存储器的起始地址。 3.要读取Flash存储器中的数据,我们可以通过以下代码实现:`data = *flash_address;`其中data是一个变量,用于存储读取到的数据。 4.要写入数据到Flash存储器中,我们可以通过以下代码实现:`*flash_address = data;`其中data是要写入的数据。 需要注意的是,STM32的Flash存储器是有写保护机制的,因此在写入数据之前,我们需要禁用写保护。可以使用以下代码禁用写保护:`FLASH->KEYR = 0x45670123; FLASH->KEYR = 0xCDEF89AB;`然后才能进行数据写入。 另外,为了确保数据的完整性,我们可以使用CRC校验来验证Flash存储器中的程序代码的正确性。可以使用库函数来计算校验和,然后将其与预期的校验和进行比较以进行验证。 综上所述,掌握STM32的Flash读写操作对于嵌入式系统的开发非常重要。上述示例代码可以帮助我们快速进行Flash读写操作,同时注意写保护和数据校验可以提高数据的安全性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值