• 关于flask-SQLAlchemy的初级使用教程


    转自  https://www.cnblogs.com/alima/p/5734992.html

     

    鉴于网上关于flask-SQLAlchemy的实例使用教程参差不齐,于此写下工作学习过程中的使用过程,以便分享交流。

    对于python关于flask有一定了解的高端玩家来说,请转至flask官方开发文档

    一.安装(install)

    需要有安装python的PC一台,介于windows系统用户比较多,本文章使用的是windows下开发。

    1.创建虚拟

    为每一个工程创建一个独立的python运行环境是我们所需要的,python提供了virtualenv,可以为我们提供这个特殊的需求。

    配置virtualenv环境

    windows环境下运行cmd.exe,使用管理员权限运行。

     pip install virtualenv

    笔者使用的python版本是3.5.2,该版本中自动配置了pip应用,使用pip指令可以很方便的下载到你所需要的python拓展库。  

    安装成功后会出现successfully installed virtualenv字样。

    PS:如果pip指令无法使用,请确认python环境下scripts是否包含在系统环境变量中的Path中。

          

    使用控制台进入你需要配置该虚拟环境的目录,使用mkdir创建工程的文件夹,笔者创建的工程名为sqlalchemy_demo

      mkdir sqlalchemy_demo

    创建虚拟Python运行环境

     virtualenv flask

    出现如下字样,说明虚拟环境创建成功

     

    进入工程文件夹,激活虚拟python运行环境

     flaskscriptsactivate

    出现如下字样显示,说明进入虚拟python运行环境成功

     

    2.安装所需要的库文件

    我们需要两个库文件,一个是flask,另一个是flask-SQLAlchemy。使用pip指令安装

     pip install flask
     pip install flask-sqlalchemy

    看到如下字样说明两个库文件安装成功

    至此,环境配置阶段结束。

    二.flask-SQLAlchemy简介

    flask-SQLAlchemy 是一个为您的flask应用增加SQLAlchemy支持的扩展。

    在python扩展库中其实包含了SQLAlchemy。在版本的不断叠加后,已经被整合到flask架构中,flask-SQLAlchemy简化在Flask中SQLAlchemy的使用,提供了有用的默认值和额外的助手来更简单地完成常见任务。

    笔者认为SQLAlchemy比较精髓的是使用ORM(对象关系映射),相对于传统连接数据库使用select,update,insert,delete操作数据表来说具有以下特点[1]:

      简单——以最基本的形式建模数据

      传达性——数据库结构被任何人都能理解的语言文档化

      精确性——基于数据模型创建正确标准化的结构

    完事无绝对,ORM有明显的优势,就会想伴随有缺点。

      隐蔽性——相对于传统使用select,update,insert,delete来说,隐藏了操作数据表的具体操作,不利于SQL的学习

      数据表结构修改难——在设计中有时会忽略了一些字段的定义,在ORM模式中只能更新映射表更新字段,而且效果远不如alter table [表名] add 字段名更新字段来的容易理解,常常会忽略一些细节

    但不得不说,ORM模式的确打开了新世界的大门,大大减少了学习及使用数据库的过程与难度。

    三.在实例中应用

    1.文件结构

    sqlalchemy_demo--->flask

             --->database.py

             --->model.py

             --->test.py

    2.创建SQLAlchemy配置文件

    database.py代码如下所示

    复制代码
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import os
    basedir = os.path.abspath(os.path.dirname(__file__))
    
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'test.db')
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    db = SQLAlchemy(app)
    
    def db_init():
        db.create_all()
    复制代码

    一句一句解释

    (1)from flask import Flask

    Flask类是flask框架的核心类,它实现了WSGI应用规范。

    (2)from flask_sqlalchemy import SQLAlchemy

    将flask-sqlchemy中内置的SQLAlchemy引用到该文件下。

    (3)import OS

    本实例中需要将数据库创建在工程的更目录下,使用python内置os库可以很方便的定位到工程路径下。

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

    将当前文件传入dirname函数中,获取当前文件所在路径,abspath函数获取该文件所在的绝对路径,以便在后边配置创建数据库的路径使用。

    (5)app = Flask(__name__) [2]

    Flask构造函数的第一个参数指定一个引入参数/importname。

    Flask框架使用这个名字进行静态资源、模板、错误信息的定位。除非你清楚的理解它的作用,通常情况下,我们总应该使用特殊变量__name__。

    Flask实例是可调用的(具有call方法),这个实例可以直接对接 WSGI服务器。

    (6)app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'test.db')

           app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    SQLALCHEMY_DATABASE_URI:用于连接数据库

      eg:sqlite:////tmp/test/db

        mysql://username:password@server/db

    SQLALCHEMY_TRACK_MODIFICATIONS:

    如果设置成True(默认情况),Flask-SQLAlchemy 将会追踪对象的修改并且发送信号。这需要额外的内存, 如果不必要的可以禁用它。如果你不显示的调用它,在最新版的运行环境下,会显示警告。

    (7)db = SQLAlchemy(app)

    SQLAlchemy函数,将刚刚创建的Flask框架,与工程所需要使用的数据库绑定到一起,以便实现工程与数据库连接,实现数据操作。

    (8)db_init()函数

    手动创建函数,以便初始化数据库

    以上就是配置database.py的一些说明,但现在还远远不够,因为当前工程的数据库在创建之后只是单纯的一个空数据库,不包含任何数据表。

    那怎么创建数据表呢,工程下需要一个映射表,以便将表格映射到数据库中,以达到创建表格的作用。

    3.创建映射表

    如下为一段创建最简单的User数据表的代码。

    复制代码
    from database import db
    
    class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(80), unique=True)
        email = db.Column(db.String(120), unique=True)
        
        def __init__(self, username, email):
            self.username = username
            self.email = email
            
        def __repr__(self):
            return '<User %r>' % self.usernam
    复制代码

    仍然是逐句解释

    (1)from database import db

    将刚刚创建的SQLAlchemy应用引用到当前文件,以便将映射表映射到数据库中,以便对于数据表的创建修改以及更新删除。

    (2)db.Model

    上边提到,当工程文件不提供映射表时将创建一个空的数据库文件。继承db.Model类,将我们当前创建的映射表和数据库db绑定在一起。此时工程文件调用create_all函数后,会自动将绑定后的映射表文件创建在数据库文件中。

    如果想探究详细绑定关系,请应用纯SQlAlchemy库,而不是flask-sqlalchemy库,之前调到了flask-sqlalchemy是简化版的SQLAlchemy,隐藏了许多细节,深入研究请转至SQLAlchemy官方文档查看应用细节。

    (3)db.Column

    创建映射表字段,以下为最常见的类型

    Integer 存储整数
    String(size) 存储有长度的字符串
    Text 存储较长的unicode文本
    DateTime 存储时间类型数据
    Float 存储浮点值
    Boolean 存储布尔值
    PickleType 存储一个python对象
    LargeBinary 存储一个任意大的二进制数据

    primary_key=True设置当前字段为主键

    uniqu=True设置当前字段不可重复

    当然也可以设置主键外键,在本文中只创建了一张数据表,在以后的文章中将说明此操作。

    (4)__init__函数

    为映射表的构造函数,一般用来初始变量,配置相关数据时使用

    (5)__repr__函数

    为以后调试输出提供接口

    4.修改database.py

    将下面的代码添加到database.py的底部

    from model import User

    Q:为什么添加到底部呢?

    A:如果你添加到头部引用model中的User,此时User类已经被引用并创建。有没有发现一个问题,User类继承了db.Model类,那么此时User类创建的时候无法找到db这个参数,因为db参数还没有创建。

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import os
    from model import User

    上边的就是错误的例子,当你引用User类时,此时db对象还没有被创建,所以调用db_init()函数时会显示ImportError: cannot import name 'User'

    复制代码
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    import os
    ...
    db = SQLAlchemy(app)
    ...
    from model import User
    复制代码

    上边的伪代码就是正确的写法,引用User类的时机至少要等到db对象创建结束后才能引用。为什么放在底部呢?为了调整文件结构,使代码看起来不是很乱,放在其他处也没关系,但请注意以下两点:

    (1)如果你打算在该文件引用User类,请保证全局引用。

    (2)无论发在哪里,至少要在db = SQLAlchemy(app)执行后,生成db对象才能进行引用,否则会导致model.py文件执行错误。

    至此,映射表文件创建成功。

    4.创建数据库

    将以上配置结束后,可以调用db_init()函数创建数据库了。

    还记得之前配置的虚拟python运行环境么,在虚拟环境下输入python,进入python指令模式进行创建

    此时,工程文件夹根目录已经生成了内置的sqlite数据库文件test.db

    四.SQLAlchemy下的数据库操作

    1.insert

    添加4个用户,将database.py中的User和db引用到文件中,此处必须引用database中的User,如果引用model中的User会造成循环引用,因为model.py中引用了database模块中的db变量

    复制代码
    from database from User,db

    u1 = User(username= 'john', email = 'john@example.com') u2 = User(username= 'susan', email = 'susan@example.com') u3 = User(username= 'mary', email = 'mary@example.com') u4 = User(username= 'david', email = 'david@example.com') db.session.add(u1) db.session.add(u2) db.session.add(u3) db.session.add(u4) db.session.commit()
    复制代码

    (1)对象 = User(字段1='值1',字段2='值2')

    相当于SQL操作INSERT INTO User VALUES(字段1='值1',字段2='值2'),并将该SQL语句赋值到一个对象上

    (2)db.session.add()

    将对于数据库的操作保存在缓存中,既然是保存到缓存中,那么该数据库语句还没有提交到数据库中

    (3)db.session.commit()

    commit()和数据库中的commit指令一样,将数据库操作提交到数据库中。

    2.select

    查询所有用户信息,并输出结果

    from database import User, db
    
    for user in User.query.all():
        print(user.id, user.name, user.email)

    以下是运行产生的结果

    (1)精确查询

    查询用户名为susan的用户邮箱

    from database import User, db
    
    u = User.query.filter_by(username='susan').first()
    print(u.email)

    (2)模糊查询

    查询邮箱以example.com结尾的用户,输出用户名及邮箱

    from database import User, db
    
    for user in  User.query.filter(User.email.ilike('%example.com')).all():
        print(user.username, user.email)

    以下是运行产生的结果

    PS:将查询出的结果按照正序或者逆序排序请使用,以username为例order_by(User.username)正序,order_by(User.username.desc())逆序

    3.update

    更新操作和查询操作有交集,请看以下代码示例,将john的邮箱修改为john@example.vip.com

    复制代码
    from database import User, db
    
    u = User.query.filter_by(username='john').first()
    u.email = 'john@example.vip.com'
    db.session.add(u)
    db.session.commit()
    复制代码

    解释起来就是首先将对象查询出来,然后将修改的字段赋值,并将查询出的对象提交到数据库,这样更新操作就结束了。

    4.delete

    将david用户删除

    from database import User, db
    
    u = User.query.filter_by(username='john').first()
    db.session.delete(u)
    db.session.commit()

    调用delete()函数,将数据传入db对象,并提交到数据库中。

    五.单体测试框架测试

    对本文提到的操作进行单体测试。(test.py文件代码如下)

    复制代码
    import unittest
    from database import User, db
    
    class TestCase(unittest.TestCase):
        def setUp(self):
            pass
    
        def tearDown(self):
            pass
    
        def test_db(self):
            u1 = User.query.filter_by(username='john').first()
            u2 = User.query.filter_by(username='susan').first()
            u3 = User.query.filter_by(username='mary').first()
            u4 = User.query.filter_by(username='david').first()
    
            assert u1.email == 'john@example.vip.com'
            assert u2.email == 'susan@example.com'
            assert u3.email == 'mary@example.com'
            assert u4.email == 'david@example.com'
    
            u5 = User(username='Alima', email='Alima@example.com')
            db.session.add(u5)
            db.session.commit()
    
            u = User.query.filter_by(username='Alima').first()
            assert u.email == 'Alima@example.com'
    
            u5.email = 'Alima@example.vip.com'
            db.session.add(u5)
            db.session.commit()
    
            u = User.query.filter_by(username='Alima').first()
            assert u.email == 'Alima@example.vip.com'
    
            db.session.delete(u5)
            db.session.commit()
    
            u = User.query.filter_by(username='Alima').first()
            assert u == None
    
    if __name__ == '__main__':
        unittest.main()
    复制代码

    执行test.py,运行结果:

    显示OK,单体测试结束。

    以上就是基本的flask-SQLAlchemy初级使用实例说明,欢迎探讨转载及引用参考,你们的回应是我的动力。

    如果文中存在错误或是某个地方说的不够精确,劳烦批评指出。

    以上,辛苦了。

  • 相关阅读:
    Java数据类型转换(自动转换和强制转换)
    Java数据类型以及变量的定义
    Java8新特性_日期时间新类 LocalDate、LocalTime、LocalDateTime
    Java8新特性_接口中的默认方法
    java8 新特性 Optional容器类
    Java8新特性 并行流与串行流 Fork Join
    Java8新特性_stream API 练习
    IDEA导入JUnit4
    Reduce:规约;Collector:收集、判断性终止函数、组函数、分组、分区
    【Linux】排序命令sort
  • 原文地址:https://www.cnblogs.com/weigege2015/p/9220932.html
Copyright © 2020-2023  润新知