Python---Flask--04--SQLAlchemy

2019/06/21 18:54
阅读数 15

大多数的数据库引擎都有对应的 Python 包,包括开源包和商业包。Flask 并不限制你使用何种类型的数据库包,因此可以根据自己的喜好选择使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。

如果这些都无法满足需求,还有一些数据库抽象层代码包供选择,例如 SQLAlchemy 和MongoEngine。你可以使用这些抽象包直接处理高等级的 Python 对象,而不用处理如表、文档或查询语言此类的数据库实体。

#使用Flask-SQLAlchemy管理数据库

安装

pip install flask-sqlalchemy

##基本使用 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|

###配置

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提供的所有功能。

###定义模型

from app import db
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin


class User(db.Model, UserMixin):
    __tablename = 'user'  #表名称

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), unique=True)
    email = db.Column(db.String(100), unique=True)
    password = db.Column(db.String(100))
    add_time = db.Column(db.DateTime, default=datetime.now)
    state = db.Column(db.Integer, default=1, comment='状态 1--有效 0--无效')

    def __repr__(self):
        return '<User %r>'% self.username
    # @property
    # def password(self):
    #     raise AttributeError('password not read')
    #
    # @password.setter
    # def password(self,password):
    #     self.password = generate_password_hash(password)


    def verify_password(self,pwd):
        """验证密码是否正确"""
        return check_password_hash(self.password, pwd)

类变量 tablename 定义在数据库中使用的表名。如果没有定义 tablename,Flask-SQLAlchemy 会使用一个默认名字,但默认的表名没有遵守使用复数形式进行命名的约定,所以最好由我们自己来指定表名。其余的类变量都是该模型的属性,被定义为 db.Column类的实例。 db.Column 类构造函数的第一个参数是数据库列和模型属性的类型。列出了一些可用的列类型以及在模型中使用的 Python 类型。 |类型|Python中的类型|说明| |---|---|---| |Integer|Int|整形| |SmallInteger|int|短整型| |BigInteger|ing或者long|不限长度| |Float|float|浮点型| |Numeric|decimal|定点数| |String|str|字符串| |Text|str|文本| |DateTime|datetime.datetime|日期和时间| |Date|datetime.date|日期| |Time|datetime.time|时间| |Boolean|bool|布尔| |Enum|str|枚举| |Interval|datetime.timedelta|时间间隔|

db.Column中其余参数指定属性的配置选项: |选项名|说明 | |---|---| |primary_key|如果设置为True,则是主键| |unique|如果设置为True,这列不允许出现重复| |index| 如果设置为True,为这列创建索引,提示查询效率| |nullable| 如果设置为True, 这列允许使用空值,如果设为Fasle,这列不允许使用空值 |default|为这列设置默认值|

###关系 关系型数据库使用关系把不同表中的行联系起来。表示用户和角色之间的一种简单关系。这是角色到用户的一对多关系,因为一个角色可属于多个用户,而每个用户都只能有一个角色。 一对多关系在模型类中的表示方法如示例所示:

class Role(db.Model):
 # ...
    users = db.relationship('User', backref='role')

class User(db.Model):
 # ...
    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() 提供额外参数,从而确定所用外键。表 列出了定义关系时常用的配置选项。 表 常用的SQLAlchemy关系选项 |选项名| 说  明| |---|---| |backref| 在关系的另一个模型中添加反向引用| |primaryjoin| 明确指定两个模型之间使用的联结条件。只在模棱两可的关系中需要指定| |lazy |指定如何加载相关记录。可选值有 select(首次访问时按需加载)、immediate(源对象加 载后就加载)、joined(加载记录,但使用联结)、subquery(立即加载,但使用子查询), noload(永不加载)和 dynamic(不加载记录,但提供加载记录的查询)| |uselist |如果设为 Fales,不使用列表,而使用标量值| |order_by |指定关系中记录的排序方式| |secondary| 指定多对多关系中关系表的名字| |secondaryjoin| SQLAlchemy 无法自行决定时,指定多对多关系中的二级联结条件|

除了一对多之外,还有几种其他的关系类型。一对一关系可以用前面介绍的一对多关系表示,但调用 db.relationship() 时要把 uselist 设为 False,把“多”变成“一”。多对一关系也可使用一对多表示,对调两个表即可,或者把外键和 db.relationship() 都放在“多”这一侧。最复杂的关系类型是多对多,需要用到第三张表,这个表称为关系表。

数据库操作

####添加

import db
user = User(username='',password='')
db.session.add(iser)
dn.session.commit()

####更新

import db
user = User.query.get(id)
user.name='aaaaaaa'
db.session.commit()

####删除

import db
user.User.query.get(id)
db.session.delete(user)
db.session.commit()

####查询 query.all() 获取全部 query.filter() 把过滤器添加到原查询上,返回一个新的查询 filter_by() 把等值过滤器添加到原查询上,返回一个新的查询 limit() 使用指定的值限制返回的结果数量,返回一个新的查询 offset() 偏移原查询返回的结果,返回一个新的结果 order_by 根据指定条件对原查询结果进行排序,返回一个新查询 group_by 根据指定条件对原查询结果进行分组,返回一个新的查询 first() 返回查询的第一个结果,如果没有返回None first_or_404() 返回查询的第一个结果,如果没有结果返回404错误 get() 返回指定主键对应的行,如果没有返回None get_or_404() 返回指定主键对应的行,如果没有找到对象,则终止请求,返回404错误 count() 返回查询结果的数量 paginate() 返回一个Paginage对象,它包含指定范围的结果

###在视图函数中操作数据库

@home.route('/register', methods=['GET', 'POST'])
def register():
    """注册"""
    form = RegisterForm()

    if form.validate_on_submit():
        data = form.data

        user = User(
            username=data['username'],
            password=generate_password_hash(data['password']),
            email=data['email']
        )
        db.session.add(user)
        db.session.commit()
        flash('注册成功')
        return redirect(url_for('home.login'))

    return render_template('/home/user/register.html', form=form)
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部