@(Flask)
表是关键。用表可以模拟程序中不同的实体。
表的列是固定的,所以这个可以对应到程序中的属性值。
关系型数据库复杂的地方在于联表查询。
一般使用集合代替表。
使用文档代替记录。
NoSQL的设计方式使得联结变得困难。
所以NoSQL的设计很多地方需要反规范化操作,才能保证效率,但是数据重复是难以避免的了。
SQL数据库擅长处理:高效且紧凑的形式存储结构化数据。这种数据库需要花费大量精力保证数据库的一致性。
NoSQL数据库:放宽了对一致性的要求,获得了性能上的优势。
划重点:中小程序来说,SQL和NoSQL数据库都OK,且性能相当。
Flask不限制使用何种类型的数据库包。
这些具体的数据库包。
通过这些包可以处理高等级的Python对象。
强大的关系型数据库框架。且提供了ORM,也有原生的SQL功能。
安装:pip install flask-sqlalchemy
数据库URL:
mysql://username:password@hostname/database
postgresql://username:password@hostname/database
sqlite:////absolute/path/to/database
sqlite:///c:/absolute/path/to/database
以MySQL为例,hostname是MySQL服务所在的主机。
可以是:
数据库服务器上可以托管多个数据库,所以要指定databasename
。
可以看到SQLite没有hostname
,username
, password
,因为SQLite不用服务器,是本地的数据库服务,安卓手机就用的是SQLite数据库。
from flask_sqlalchemy import SQLAlchemy #引入数据库管理包
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir,'data.sqlite')
db = SQLAlchemy(app)
db是SQLAlchemy类实例,表示的就是程序使用的数据库,通过db可以获得SQLAlchemy提供的所有功能。
模型的含义:程序使用的持久化实体。
一般来说,数据库的天然属性就是持久化。
ORM下,模型是一个Python类,类的属性对应到数据库表中的列。
SQLAlchemy创建的数据库实例为模型提供了:
用于定义模型的结构。
#定义模型
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 '' % self.name
类变量__tablename__
定义在数据库中说那个的表名。
db.Column()
类构造函数参数:
第一个参数类型不列举了,重点看第二个可选参数。
__repr__()
函数返回一个具有可读性的字符串表示模型,用于调试和测试。
关系型数据库使用关系将不同的表中的行联系起来。
#在Role类中定义
users = db.relationship('User',backref='role')
#role_id位于users表中,这个是外键
role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
db.relationship()
第一个参数表明这个关系的另一端是哪个模型,如果模型尚未定义,可使用字符串形式执行。
backref
参数向User
模型中添加一个role
属性。从而定义反向关系:通过这个属性可以替代role_id
访问Role模型。此时可以获取的是模型对象,不是外键的值。
注:关于反向关系的理解,可以点击参考相关解释。
定义关系时常用的配置选项:
select
首次访问时按需加载immediate
源对象加载后就加载joined
加载记录但使用联结subquery
立即加载,但使用子查询noload
永不加载dynamic
不加载记录,但提供加载记录的查询注:上面这些不是特别清晰,需要在实例中阐述。
方法:db.create_all()
函数
python hello.py shell
>>> from hello import db
>>> db.create_all()
删除旧表:db.drop_all()
#同样在shell下
>>> 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)
>>> admin_role.name = 'Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()
>>> db.session.delete(mod_role)
>>> db.session.commit()
SQLAlchemy为每个模型类都提供给了query对象。
最基本的查询是:Role.query.all()
将返回表中的所有记录。
自然这个是很粗糙的,需要加条件过滤。
过滤器
进行更精确的数据库查询。
User.query.filter_by(role=user_role).all()
可以很方便查询SQLAlchemy生成的原生SQL查询语句:
>>> str(User.query.filter_by(role=user_role))
将得到原生的SQL语句。
指定过滤器后,通过调用all()
执行查询。
当然也有其他触发执行方法:
语法与上面在终端的用法相同。
每次启动shell会话需要导入数据库实例和模型,为了避免重复,做些配置即可。
from flask_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))
用到再详谈。