Flask 学习笔记(三)-ORM

Posted: 2018-06-10  By  vilay  |  Views(475)

简述

SQLAlchemy是个非常优秀的orm,flask可以根据自己的爱好使用orm,但是既然使用flask,首选当然是flask-sqlalchemy。

安装

pip3 install flask-sqlalchemy

初始化

from flask import Flask,render_template
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1:3306/flask?charset=utf8'
# 初始化
db = SQLAlchemy(app)


class User(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(40), unique=True)
        mobile = db.Column(db.String(20), unique=True)
        password = db.Column(db.String(255))

        def __init__(self, username, mobile, password):
                self.username = username
                self.mobile = mobile
                self.password = password

        def __repr__(self):
                return '<User %r>' % self.username

访问页面的时候报错No module named 'MySQLdb'

解决方法:安装pymysql

pip3 install pymysql

数据对象创建

class Users(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(40), unique=True)
        mobile = db.Column(db.String(20), unique=True)
        password = db.Column(db.String(255))

        def __init__(self, username, mobile, password):
                self.username = username
                self.mobile = mobile
                self.password = password

        def __repr__(self):
                return '<User %r>' % self.username

备注:默认情况下Users对象是数据库表users的映射,如果类名与数据库表名不一致,可以通过属性__tablename__=users指定

指定表名示例:

class Users(db.Model):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(40), unique=True)
        mobile = db.Column(db.String(20), unique=True)
        password = db.Column(db.String(255))

        def __init__(self, username, mobile, password):
                self.username = username
                self.mobile = mobile
                self.password = password

        def __repr__(self):
                return '<User %r>' % self.username

正确使用

先上代码(文件命名为hello.py):

import os
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy

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

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hello vilay'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:12346@127.0.0.1:3306/flask?charset=utf8'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True

db = SQLAlchemy(app)
manager = Manager(app)


class User(db.Model):
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64),unique=True)
        role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

        def __repr__(self):
                return '<User %r>' % self.name

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 '<User %r>' % self.name

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

if __name__ == '__main__':
        manager.run()

上面代码,引入了两个扩展,Flask-Script和Flask-SQLAlchemy

进入命令行,执行命令

python3 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_vilay = User(name='vilay',role=admin_role)
>>> user_city = User(name='city',role=mod_role)
>>> user_dity = User(name='dity',role=user_role)

是不是觉得插入数据库了,我也是这么觉得的。但是并没有插入数据库。

可以执行下面命令试试

>>> print(admin_role.id)
None

这些新建对象的 id 属性并没有明确设定,因为主键是由 Flask-SQLAlchemy 管理的。现在这些对象只存在于 Python 中,还未写入数据库。因此 id 尚未赋值。通过数据库会话管理对数据库所做的改动,在 Flask-SQLAlchemy 中,会话由 db.session 表示。准备把对象写入数据库之前,先要将其添加到会话中,执行下面的命令

>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_vilay)
>>> db.session.add(user_city)
>>> db.session.add(user_dity)

也可以这样

>>> db.session.add_all([admin_role, mod_role, user_role,user_vilay, user_city, user_dity])

再执行提交命令

>>> db.session.commit()

再去看数据库,数据生成成功了。

修改行

>>> admin_role.name='Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()

删除行

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

查询

>>> Role.query.all()

基本操作完成。

每次重启都需要from hello import User,Role太麻烦了,我们可以这么做

在上面代码中新引入两句

from flask_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))

#后面省略

数据库迁移

示例代码:

from flask_migrate import Migrate, MigrateCommand
# 中间省略
migrate = Migrate(app,db)
manager.add_command('db',MigrateCommand)
#后面省略

执行

python3 hello.py db init #始化数据库,会创建一个migations文件夹
python3 hello.py db migrate -m 'init' #创建迁移历史
python3 hello.py db upgrade # 更新迁移