flask SQLAlchemy 数据库操作

数据库URL必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。将SQLALCHEMY_COMMIT_ON_TEARDOWN键,将其设为True时,每次请求结束后都会自动提交数据库中的变动。
简单的配置SQLite数据库

from flask_sqlalchemy import SQLAlchemy

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

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
app.config['SQLALCHEMY_DATABASE_URI'] =\
    'sqlite:///' + os.path.join(basedir, 'data.sqlite') # 程序使用的数据库URL必须保存到SQLALCHEMY_DATABASE_URI变量
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True  # 每次请求结束都会自动提交事务

定义模型
Flask-SQLAlchemy要求每个模型都要定义主键,这一列经常命名为id

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


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

    def __repr__(self):
        return '' % self.username

tablename定义在数据库中使用的表名。添加到User模型中的role_id列被定义为外键,就是这个外键建立了关系。传给db.ForeignKey()的参数‘role.id’表明,这列的值是roles表中的行的id值。
添加到Role模型中的users属性代表这个关系的面向对象视角。对于一个Role类的实例,其users属性将返回与角色相关联的用户组成的列表。db.relationship()的第一个参数表明这个关系的另一端是那个模型。
db.relationship()中的backref参数向User模型中添加一个role模型,从而定义反向关系。这一属性可替代role_id访问Role模型,此时获取的是模型对象,而不是外键的值。
db.relationship()表示一对一关系时,把uselist设置为False,把多变成一

接下来在flask-script中操作数据库

python hello.py shell

创建表

from hello import db
db.create_all()
db.drop_all()
db.create_all()

插入行

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)
user_david = User(username='david', role=user_role)

db.session.add(admin_role)
或者可以批量添加到会话中
db.session.add_all([admin_role,mod_role,...,user_david])
提交给数据库
db.session.commit()

修改行

admin_role.name = 'test'
db.session.add(admin_role)
db.session.commit()

删除行

db.session.delete(mod_role)
db.session.commit()

查询行

User.query.filter_by(role=user_role).all()
user_role = Role.query.filter_by(name='User').first()

常用的SQLALchemy查询过滤器

过滤器 说明
filter() 把过滤器添加到原查询上
filter_by() 把等值过滤器添加到原查询上
limit() 限制原查询返回的结果数量
offset() 偏移原始查询返回的结果
order_by() 根据指定条件对原查询进行排序
group_by() 根据指定条件对原查询结果进行分组

users = db.relationship('User', backref='role', lazy='dynamic') 加入了lazy=’dynamic’参数,从而禁止自动执行查询,user_role.users会返回一个尚未执行的查询,因此可以在其上添加过滤器
user_role.users.order_by(User.username).all()

Flask-SQLAlchemy要求每个模型都要定义主键,这一列经常命名为id

最常用的SQLALCHEMY列选项

选项名 说明
primary_key 主键
unique 是否允许重复值
index 设为True,为这一 列建立索引
nullable 设为True,允许使用空
default 默认值

集成Python Shell

每次启动Shell会话都要导入数据库实例和模型,可以配置让Flask-script的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))

再次执行 python hello.py shell
>>> db
'sqlite:///C:\\Users\\yuchuan\\PycharmProjects\\flasky\\data.sqlite'>
>>> app
'hello'>
>>> User
<class '__main__.User'>

在视图函数中操作数据库

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        #从数据库中查询是否存在
        user = User.query.filter_by(username=form.name.data).first()
        if user is None:
            user = User(username=form.name.data)
            db.session.add(user)
            session['known']=False
        else:
            session['known']=True
        session['name']=form.name.data
        form.name.data = ''
        return redirect(url_for('index'))
    return render_template('index.html', form=form, known=session.get('known', False), name=session.get('name'))

index.html

{% block page_content %}
<div class="page-header">
    <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!h1>
{% if not known %}
<p>Pleased to meet you !p>
{% else %}
<p>Happy to see you again!p>
{% endif %}
div>
{{ wtf.quick_form(form) }}
{% endblock %}

使用Flask-Migrate进行数据库迁移

from flask.ext.migrate import Migrate,MigrateCommand
migrate = Migrate(app,db)
# 第一个参数是Flask的实例,第二个参数是Sqlalchemy数据库实例

manager.add_command('db', MigrateCommand)
# manager是Flask-Script的实例,这条语句在flask-script中添加一个db命令

在命令行中

python manager.py db init # 创建迁移仓库
python manager.py db migrate -m "initial migration" 创建迁移脚本
python manager.py db upgrade 更新数据库

你可能感兴趣的:(数据库,python,flask,python,Flask,SQLAlchemy)