Flask后端笔记(四)数据库的使用、查询等操作

数据库的设置

在这里插入图片描述

Web应用中普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储在表中,表用来给应用的实体建模,表的列数是固定的,行数是可变的。它使用结构化的查询语言。关系型数据库的列定义了表中表示的实体的数据属性。比如:商品表里有name、price、number等。 Flask本身不限定数据库的选择,你可以选择SQL或NOSQL的任何一种。也可以选择更方便的SQLALchemy,类似于Django的ORM。SQLALchemy实际上是对数据库的抽象,让开发者不用直接和SQL语句打交道,而是通过Python对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升。

SQLAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLAlchemy操作的flask扩展。

数据库安装

安装服务端

sudo apt-get install mysql-server
安装客户端

sudo apt-get install mysql-client
sudo apt-get install libmysqlclient-dev

数据库的基本命令

登录数据库

mysql -u root -p
创建数据库,并设定编码

create database <数据库名> charset=utf8;
显示所有数据库

show databases;

在Flask中使用mysql数据库

需要安装一个flask-sqlalchemy的扩展。
pip install flask-sqlalchemy
要连接mysql数据库,仍需要安装flask-mysqldb

pip install flask-mysqldb
或者
pip install MySQL-Python(Python2优先安装)

使用Flask-SQLAlchemy管理数据库

使用Flask-SQLAlchemy扩展操作数据库,首先需要建立数据库连接。数据库连接通过URL指定,而且程序使用的数据库必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。

对比下Django和Flask中的数据库设置:

Django的数据库设置:
在这里插入图片描述

Flask的数据库设置:

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/test3'

常用的SQLAlchemy字段类型

类型名 python中类型 说明
Integer int 普通整数,一般是32位
SmallInteger int 取值范围小的整数,一般是16位
BigInteger int或long 不限制精度的整数
Float float 浮点数
Numeric decimal.Decimal 普通整数,一般是32位
String str 变长字符串
Text str 变长字符串,对较长或不限长度的字符串做了优化
Unicode unicode 变长Unicode字符串
UnicodeText unicode 变长Unicode字符串,对较长或不限长度的字符串做了优化
Boolean bool 布尔值
Date datetime.date 时间
Time datetime.datetime 日期和时间
LargeBinary str 二进制文件

常用的SQLAlchemy列选项

选项名 说明
primary_key 如果为True,代表表的主键
unique 如果为True,代表这列不允许出现重复的值
index 如果为True,为这列创建索引,提高查询效率
nullable 如果为True,允许有空值,如果为False,不允许有空值
default 为这列定义默认值

常用的SQLAlchemy关系选项

选项名 说明
backref 在关系的另一模型中添加反向引用
primary join 明确指定两个模型之间使用的联结条件
uselist 如果为False,不使用列表,而使用标量值
order_by 指定关系中记录的排序方式
secondary 指定多对多中记录的排序方式
secondary join 在SQLAlchemy中无法自行决定时,指定多对多关系中的二级联结条件

demo.py

# coding:utf-8

from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)


class Config(object):
    """配置参数"""
    # sqlalchemy的配置参数
    SQLALCHEMY_DATABASE_URI = "mysql://root:[email protected]:3306/db_python04"

    # 设置sqlalchemy自动更跟踪数据库
    SQLALCHEMY_TRACK_MODIFICATIONS = True


app.config.from_object(Config)

# 创建数据库sqlalchemy工具对象
db = SQLAlchemy(app)


class Role(db.Model):
    """用户角色/身份表"""
    __tablename__ = "tbl_roles"
	# 定义列对象
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32), unique=True)
    users = db.relationship("User", backref="role")
    
	#repr()方法显示一个可读字符串
    def __repr__(self):
        """定义之后,可以让显示对象的时候更直观"""
        return "Role object: name=%s" % self.name


# 表名的常见规范
# ihome -> ih_user   数据库名缩写_表名
# tbl_user  tbl_表名
# 创建数据库模型类
class User(db.Model):
    """用户表"""
    __tablename__ = "tbl_users"  # 指明数据库的表名

    id = db.Column(db.Integer, primary_key=True)  # 整型的主键,会默认设置为自增主键
    name = db.Column(db.String(64), unique=True)
    email = db.Column(db.String(128), unique=True)
    password = db.Column(db.String(128))
    role_id = db.Column(db.Integer, db.ForeignKey("tbl_roles.id"))

    def __repr__(self):
        return "User object: name=%s" % self.name


if __name__ == '__main__':
    # 清除数据库里的所有数据
    db.drop_all()

    # 创建所有的表
    db.create_all()

    # 创建对象
    role1 = Role(name="admin")
    # session记录对象任务
    db.session.add(role1)
    # 提交任务到数据库中
    db.session.commit()

    role2 = Role(name="stuff")
    db.session.add(role2)
    db.session.commit()

    us1 = User(name='wang', email='[email protected]', password='123456', role_id=role1.id)
    us2 = User(name='zhang', email='[email protected]', password='201512', role_id=role2.id)
    us3 = User(name='chen', email='[email protected]', password='987654', role_id=role2.id)
    us4 = User(name='zhou', email='[email protected]', password='456789', role_id=role1.id)

    # 一次保存多条数据
    db.session.add_all([us1, us2, us3, us4])
    db.session.commit()

查询操作

# 查询所有
Role.query.all()
Out[2]: [<db_demo.Role at 0x10388d190>, <db_demo.Role at 0x10388d310>]

In [3]: li = Role.query.all()

In [4]: li
Out[4]: [<db_demo.Role at 0x10388d190>, <db_demo.Role at 0x10388d310>]

In [5]: r = li[0]

In [6]: type(r)
Out[6]: db_demo.Role

In [7]: r.name
Out[7]: u'admin'

# 查询第一条
In [8]: Role.query.first()
Out[8]: <db_demo.Role at 0x10388d190>

In [9]: r = Role.query.first()

In [10]: r.name
Out[10]: u'admin'

#  根据主键id获取对象
In [11]: r = Role.query.get(2)

In [12]: r
Out[12]: <db_demo.Role at 0x10388d310>

In [13]: r.name
Out[13]: u'stuff'

# 另一种查询方式
In [15]: db.session.query(Role).all()
Out[15]: [<db_demo.Role at 0x10388d190>, <db_demo.Role at 0x10388d310>]

In [16]: db.session.query(Role).get(2)
Out[16]: <db_demo.Role at 0x10388d310>

In [17]: db.session.query(Role).first()
Out[17]: <db_demo.Role at 0x10388d190>

常用的SQLAlchemy查询过滤器

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

常用的SQLAlchemy查询执行器

方法 说明
all() 以列表形式返回查询的所有结果
first() 返回查询的第一个结果,如果未查到,返回None
first_or_404() 返回查询的第一个结果,如果未查到,返回404
get() 返回指定主键对应的行,如不存在,返回None
get_or_404() 返回指定主键对应的行,如不存在,返回404
count() 返回查询结果的数量
paginate() 返回一个Paginate对象,它包含指定范围内的结果

查询:过滤器

In [18]: User.query.filter_by(name="wang")
Out[18]: <flask_sqlalchemy.BaseQuery at 0x1038c90d0>

In [19]: User.query.filter_by(name="wang").all()
Out[19]: [<db_demo.User at 0x1038c87d0>]

In [20]: User.query.filter_by(name="wang").first()
Out[20]: <db_demo.User at 0x1038c87d0>

In [21]: user = User.query.filter_by(name="wang").first()

In [22]: user.name
Out[22]: u'wang'

In [23]: user.email
Out[23]: u'[email protected]'

In [24]: User.query.filter_by(name="wang", role_id=1).first()
Out[24]: <db_demo.User at 0x1038c87d0>

In [25]: User.query.filter_by(name="wang", role_id=2).first()

In [26]: user = User.query.filter_by(name="wang", role_id=2).first()

In [27]: type(user)
Out[27]: NoneType

In [28]: user = User.query.filter(User.name=="wang", User.role_id==1).first()

In [29]: user
Out[29]: <db_demo.User at 0x1038c87d0>

In [30]: user.name
Out[30]: u'wang'


逻辑非,返回名字不等于wang的所有数据。

User.query.filter(User.name!='wang').all()
逻辑非

逻辑与,需要导入and,返回and()条件满足的所有数据。

from sqlalchemy import and_
User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()

and_

逻辑或,需要导入or_

from sqlalchemy import or_
User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()

or_

not_ 相当于取反

from sqlalchemy import not_
User.query.filter(not_(User.name=='chen')).all()

在这里插入图片描述
偏移

# offset偏移  跳过几条
In [36]: User.query.offset(2).all()
Out[36]: [<db_demo.User at 0x1038c0950>, <db_demo.User at 0x1038ef310>]

In [37]: li = User.query.offset(2).all()

In [38]: li[0].name
Out[38]: u'chen'

In [39]: li[1].name
Out[39]: u'zhou'


In [42]: li = User.query.offset(1).limit(2).all()

In [43]: li
Out[43]: [<db_demo.User at 0x1038fd990>, <db_demo.User at 0x1038c0950>]

In [44]: li[0].name
Out[44]: u'zhang'

In [45]: li[1].name
Out[45]: u'chen'

排序

In [50]: User.query.order_by("-id").all()
Out[50]:
[<db_demo.User at 0x1038ef310>,
 <db_demo.User at 0x1038c0950>,
 <db_demo.User at 0x1038fd990>,
 <db_demo.User at 0x1038c87d0>]

In [51]:

In [51]: li = User.query.order_by(User.id.desc()).all()

In [52]: li
Out[52]:
[<db_demo.User at 0x1038ef310>,
 <db_demo.User at 0x1038c0950>,
 <db_demo.User at 0x1038fd990>,
 <db_demo.User at 0x1038c87d0>]

In [53]: li[0].name
Out[53]: u'zhou'

In [54]: li[3].name
Out[54]: u'wang'

分组

In [55]: from sqlalchemy import func

In [56]: db.session.query(User.role_id, func.count(User.role_id)).group_by(User.role_id)
Out[56]: <flask_sqlalchemy.BaseQuery at 0x103a38050>

In [57]: db.session.query(User.role_id, func.count(User.role_id)).group_by(User.role_id).all()
Out[57]: [(1L, 2L), (2L, 2L)]



在这里插入图片描述

从角色查询用户和从用户查询角色

In [61]: ro = Role.query.get(1)

In [62]: type(ro)
Out[62]: db_demo.Role

In [63]: ro.users
Out[63]: [<db_demo.User at 0x1038c87d0>, <db_demo.User at 0x1038ef310>]

In [64]: ro.users[0].name
Out[64]: u'wang'

In [65]: ro.users[1].name
Out[65]: u'zhou'


In [67]: user
Out[67]: <db_demo.User at 0x1038c87d0>

In [68]: user.role_id
Out[68]: 1L

In [69]: Role.query.get(user.role_id)
Out[69]: <db_demo.Role at 0x10388d190>

In [70]: user.role
Out[70]: <db_demo.Role at 0x10388d190>

In [71]: user.role.name
Out[71]: u'admin'

优化查询显示
在这里插入图片描述

在这里插入图片描述
更新

# 更新
In [14]: User.query.filter_by(name="zhou").update({
    
    "name": "python", "email": "[email protected]"})
Out[14]: 1L

In [15]: db.session.commit()

In [16]:

删除



# 删除
In [16]: user = User.query.get(3)

In [17]: db.session.delete(user)

In [18]: db.session.commit()

In [19]:

先查询后更新或删除
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_27251475/article/details/120992900