python flask扩展_flask 常用扩展

SQLAlchemy 是一个很强大的关系型数据库框架,支持多种数据库后台。SQLAlchemy 提供了高层 ORM,也提供了使用数据库原生 SQL 的低层功能

# 安装

pip install flask-sqlalchemy

# 配置连接

from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)

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

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite') # 程序使用的数据库 URL 必须保存到 Flask 配置对象的 SQLALCHEMY_DATABASE_URI 键中

app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True # SQLALCHEMY_COMMIT_ON_TEARDOWN 键,将其设为 True时,每次请求结束后都会自动提交数据库中的变动

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True # 新版本需要加的配置

db = SQLAlchemy(app)

在 Flask-SQLAlchemy 中,数据库使用 URL 指定

数据库引擎 URL

MySQL mysql://username:password@hostname/database

Postgres postgresql://username:password@hostname/database

SQLite(Unix) sqlite:absolute/path/to/database

SQLite(Windows) sqlite:///c:/absolute/path/to/database

Oracle oracle://scott:tiger@127.0.0.1:1521/sidname

# 定义模型

模型这个术语表示程序使用的持久化实体。在 ORM 中,模型一般是一个 Python 类,类中的属性对应数据库表中的列

class Role(db.Model):

__tablename__ = 'roles' # 类变量 __tablename__ 定义在数据库中使用的表名

id = db.Column(db.Integer, primary_key=True)

name = db.Column(db.String(64), unique=True)

def __repr__(self): # __repr()__ 方法返回一个具有可读性的字符串表示模型

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类型 说  明

Integer int 普通整数,一般是 32 位

SmallInteger int 取值范围小的整数,一般是 16 位

BigInteger int 或 long 不限制精度的整数

Float float 浮点数

Numeric decimal.Decimal 定点数

String str 变长字符串

Text str 变长字符串,对较长或不限长度的字符串做了优化

Unicode unicode 变长 Unicode 字符串

UnicodeText unicode 变长 Unicode 字符串,对较长或不限长度的字符串做了优化

Boolean bool 布尔值

Date datetime.date 日期

Time datetime.time 时间

DateTime datetime.datetime 日期和时间

Interval datetime.timedelta 时间间隔

Enum str 一组字符串

PickleType 任何 Python 对象 自动使用 Pickle 序列化

LargeBinary str 二进制文件

最常使用的SQLAlchemy列选项

选项名 说  明

primary_key 如果设为 True ,这列就是表的主键

unique 如果设为 True ,这列不允许出现重复的值

index 如果设为 True ,为这列创建索引,提升查询效率

nullable 如果设为 True ,这列允许使用空值;如果设为 False ,这列不允许使用空值

default 为这列定义默认值

# 关系

class Role(db.Model):

'''

users 属性代表这个关系的面向对象视角。对于一个 Role 类的实例,其 users 属性将返回与角色相关联的用户组成的列表。 db.relationship() 的第一个参数表明这个关系的另一端是哪个模型。如果模型类尚未定义,可使用字符串形式指定。

db.relationship() 中的 backref 参数向 User 模型中添加一个 role 属性,从而定义反向关系。这一属性可替代 role_id 访问 Role 模型,此时获取的是模型对象,而不是外键的值.

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

'''

__tablename__ = 'roles' # 类变量 __tablename__ 定义在数据库中使用的表名

id = db.Column(db.Integer, primary_key=True)

name = db.Column(db.String(64), unique=True)

users = db.relationship('User', backref='role')

def __repr__(self): # __repr()__ 方法返回一个具有可读性的字符串表示模型

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)

role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) # role_id 列被定义为外键,传给 db.ForeignKey() 的参数 'roles.id' 表明,这列的值是 roles 表中行的 id 值

def __repr__(self):

return '' % self.username

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

常用的SQLAlchemy关系选项

选项名 说  明

backref 在关系的另一个模型中添加反向引用

primaryjoin 明确指定两个模型之间使用的联结条件。只在模棱两可的关系中需要指定

lazy 指定如何加载相关记录。可选值有 select (首次访问时按需加载)、 immediate (源对象加载后就加载)、 joined (加载记录,但使用联结)、 subquery (立即加载,但使用子查询),noload (永不加载)和 dynamic (不加载记录,但提供加载记录的查询)

uselist 如果设为 Fales ,不使用列表,而使用标量值

order_by 指定关系中记录的排序方式

secondary 指定多对多关系中关系表的名字

secondaryjoin SQLAlchemy 无法自行决定时,指定多对多关系中的二级联结条件

# 数据库操作

创建表

db.create_all() # 如果数据库表已经存在于数据库中,那么 db.create_all()不会重新创建或者更新这个表

db.drop_all() # 删除表

插入行

>>>from hello import Role, User

>>>admin_role = Role(name='Admin')

>>>user_john = User(username='john', role=admin_role) # role=admin_role------> db.relationship() 中的 backref 参数向 User 模型中添加一个 role 属性。role 属性也可使用,虽然它不是真正的数据库列,但却是一对多关系的高级表示

>>>db.session.add(admin_role) # 或者简写成:db.session.add_all([admin_role, user_john])

>>>db.session.add(user_john)

>>>db.session.commit()

修改行

>>>admin_role.name = 'Administrator'

>>>db.session.add(admin_role)

>>>db.session.commit()

删除行

>>>db.session.delete(mod_role)

>>>db.session.commit()

回滚

db.session.rollback()

查询行

>>>Role.query.all() # 查询所有

[, ]

>>>User.query.filter_by(role=admin_role).all() # 过滤器

[]

>>>str(User.query.filter_by(role=user_role)) # 查看原生sql

'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'

# 关系的查询

关系和查询的处理方式类似

>>>users = admin_role.users

>>>users

[]

>>>users[0].role

这个例子中的 user_role.users 查询有个小问题。执行 user_role.users 表达式时,隐含的查询会调用 all() 返回一个用户列表。 query 对象是隐藏的,因此无法指定更精确的查询过滤器

我们修改关系的设置,加入 lazy = 'dynamic' 参数,从而禁止自动执行查询

class Role(db.Model):

__tablename__ = 'roles'

id = db.Column(db.Integer, primary_key=True)

name = db.Column(db.String(64), unique=True)

users = db.relationship('User', backref='role', lazy='dynamic')

def __repr__(self):

return '' % self.name

这样配置关系之后, user_role.users 会返回一个尚未执行的查询,因此可以在其上添加过滤器:

>>>user_role.users.order_by(User.username).all()

[, ]

>>>user_role.users.count()

2

常用的SQLAlchemy查询过滤器

过滤器 说  明

filter() 把过滤器添加到原查询上,返回一个新查询 # User.query.filter(User.role==user_role).all()

filter_by() 把等值过滤器添加到原查询上,返回一个新查询 # User.query.filter_by(role=user_role).all() Role.query.filter_by(name='User').all()

limit() 使用指定的值限制原查询返回的结果数量,返回一个新查询

offset() 偏移原查询返回的结果,返回一个新查询

order_by() 根据指定条件对原查询结果进行排序,返回一个新查询

group_by() 根据指定条件对原查询结果进行分组,返回一个新查询

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

方 法 说  明

all() 以列表形式返回查询的所有结果

first() 返回查询的第一个结果,如果没有结果,则返回 None

first_or_404() 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应

get() 返回指定主键对应的行,如果没有对应的行,则返回 None

get_or_404() 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应

count() 返回查询结果的数量

paginate() 返回一个 Paginate 对象,它包含指定范围内的结果

# 继承python shell

可以在启动shell的时候自动加载db配置,导入数据库实例和模型

from flask_script import Manager, Shell

app = Flask(__name__)

manager = Manager(app)

def make_shell_context():

return dict(app=app, db=db, User=User, Role=Role)

manager.add_command("shell", Shell(make_context=make_shell_context))

if __name__ == '__main__':

manager.run()

启动shell: python hello.py shell

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值