利用pycharm学习flask(十)
本文内容:
1.使用Flask-SQLAlchemy管理数据库
2.定义模型
3.关系
使用Flask-SQLAlchemy管理数据库
Flask-SQLAlchemy是一个Flask扩展,简化Flask程序使用SQLAlchemy的操作,首先我们在pycharm中安装这个插件。
在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 |
上述URL中,hostname表示MySQL服务所在的主机,可以是本地主机(localhost),也可以是远程服务器。数据库服务器上可以托管多个数据库,所以database表示要使用的数据库名。username和password表示数据库用户名和密码。SQLite数据库不需要使用服务器,因此不用指定hostname、username和password。URL中的database是硬盘上文件的文件名。
URL必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。配置对话中的SQLALCHEMY_COMMIT_ON_TEARDOWN键设置为True时,每次请求结束后都会自动提交数据库中的变动。
修改hello.py,配置数据库
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)
db对象是SQLAlchemy类的实例,表示程序使用的数据库,同时还获得了Flask-SQLAlchemy提供的所有功能。
定义模型
在ORM中,模型一般是一个Python类,类中的属性对应数据表中的列。
修改hello.py,定义上图中的Role和User模型(表)
class Role(db.Model):
__tablename__ = 'roles'
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):
__teblename__ = '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
类变量tablename是数据库中使用的表名,如果不定义,flask会使用一个默认的名字。其余的类变量都是该模型的属性,被定义为db.Column类的实例。
db.Column类构造函数的第一个参数是数据库列和模型属性的类型,下图为一些可用的列类型以及在模型中使用的Python类型。
db.Column中其余的参数指定属性的配置选项如下图
Flask-SQLAlchemy要求每个模型都要定义主键,一般命名为id。
上面两个模型都定义了repr()方法,返回一个具有可读性的字符串表示模型,可在调试和测试时使用。
关系
关系型数据库使用关系把不同表中的行联系起来。
修改hello.py,表示一对多关系
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')
def __repr__(self):
return '<Role %r>' % self.name
class User(db.Model):
__teblename__ = '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'))
关系使用users表中的外键连接了两行。添加到User模型中的role_id列被定义为外键。它传递给db.ForeignKey()的参数'roles.id'表明,这列的值是roles表中行的id值。
添加到role模型中的users属性代表这个关系的面向对象视角。对于一个role类的实例,其users属性将返回与角色相关联的用户组成的列表。db.relationship()的第一个参数表明这个关系的另一端是哪个模型。如果模型类尚未定义,可使用字符串形式指定。
db.relationship()中的backref参数向User模型中添加一个role属性,从而定义反向关系。这一属性可替代role_id访问role模型,此时获取的是模型对象,而不是外键的值。
大多数情况下,db.relationship()都能自行找到关系中的外键,但有时却无法决定把哪一列作为外键。例如如果User模型中有两个或以上的列定义为role模型的外键,SQLAlchemy就不知道该用哪个。如果无法决定外键,你就要为db.relationship()提供额外参数,确定使用外键,下图列出定义关系时常用的配置选项。
除了一对多外,一对一类型可以用一对多关系表示,但调用db.relationship()时要把uselist设为False,把“多”变为“一”。多对一关系也可以用一对多表示,对调两个表即可,或者把外键和db.relationship()都放在“多”这一侧。多对多关系以后再说。