数据库按照一定规则保存程序数据,程序再发起查询去取回所需的数据。分为文档数据库(NoSQL)和键值数据库(SQL),具体可去百度百科看介绍,这类不再赘述。Web程序最常用是基于关系模型的数据库
数据库框架
大多数数据库引擎都有对应的python包,除此之外还可以选择数据库抽象层和SQLAlchemy和MongoEngine。
这里采用Flask-SQLAlchemy管理数据库。接下来用的数据是MySQL,安装方法见[随笔]
(http://www.jianshu.com/p/9b48ae42e92a)
然而我用的flask搭建python3.5平台,实际操作过程中出现提示未导入mysqldb(mysql-python)库,目前只支持python2.7。所以网站改用python自带轻量级SQLite。
hello.py:配置数据库
from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+os.path.join(basedir,'data.sqlite')
#数据库位置
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] =True
#每次请求结束后自动提交数据库中的变动
db = SQLAlchemy(app)
flask quickstart定义数据位置输入的是
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
差异在这里用basedir获取该文件所在路径,所以数据库与hello.py同级
hello.py:定义Role和User模型
class NameFome(Form):
name = StringField('who are you', validators=[Required()])
submit = SubmitField('Submit')
class Role(db.Model):
__tablename__ = 'roles' #定义数据库中使用的表名
#模型的属性,定义为db.Column的实例
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64), unique=True)
#可选,定义__repr__方法,返回一个具有可读性的字符串表示模型
def __repr__(self):
return '<Role %r>' %self.name
class User(db.Model):
__table__name = '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
hello.py:关系
class Role(db.Model):
#...
uers = db.relationship('User',backref='role')
class User(db.Model):
#...
role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
所谓关系就是Role和User之间建立了链接。关系用users表中的外键(ForeignKey)连接了两行。
添加到users表中role_id被定义为外键,传给db.ForeignKey()的参数表明这列的值是roles表中的id值
添加到Role模型中的users属性代表这个关系的面向对象视角。db.relationship()第一个参数表明这个关系的另一端是哪个模型。backref参数向User模型中添加一个role属性,这一属性可替代role_id访问Role模型,此时获取的是模型对象而不是外键的值
上面这段话太复杂了,不懂多看几遍,下面介绍一下常用的数据库操作。
预先操作:
python hello.py shell
- 创建表
首先,让flask-sqlalchemy根据模型类参加数据库.
from hello import db
db.create_all() - insert
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=mod_role)
user_david = User(username='David',role=user_role)
模型的构造函数(Role())接受的参数(name,username)是使用关键字参数指定的模型属性初始值
通过会话(session)管理数据库所做的改动。在flask_sqlalchemy中,会话由db.session表示
添加
多个添加
db.session.add_all([admin_role, mod_role,user_role,user_john,user_susan, user_david])
单个添加
db.session.add(xxx)
提交
db.session.commit()
回滚
db.session.rollback()
始终保证在会话中提交改动,这样可以避免因部分更新导致数据的不一致性。
3.修改行
admin_role.name = 'Administrator'
db.session.add(admin_role)
db.session.commit()
4.删除行
db.session.delete(mod_role)
db.session.commit()
5.查询行
Role.query.all()
User.query.filter_by(role=user_role).all()
一旦退出shell会话,这些例子中创建的对象不会以python对象的形式存在,而是作为各自数据库中的行。重新打开shell会话,需要从数据库中读取行,再重新创建python对象。
如果每次启动shell会话都要导入数据库实例和模型,那么真的要难过死了。这个可以通过为shell增加一个上下文解决
from flask.ext.script import Manager, 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))