Flask中sqlachemy的使用

版权声明:FatPuffer https://blog.csdn.net/qq_42517220/article/details/88797649

SQLAlchemy

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

SQLAlchemy在flask中的应用

(1)安装依赖包

在Flask中使用mysql数据库,需要安装一个flask-sqlalchemy的扩展

pip install flask-sqlalchemy

要连接mysql数据库,仍需要安装数据库驱动

pip install MySQL-Python

如果报错:信息如下

Collecting mysql-python
  Downloading https://files.pythonhosted.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip (108kB)
    100% |████████████████████████████████| 112kB 148kB/s 
    Complete output from command python setup.py egg_info:
    sh: mysql_config: command not found
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-WXInHg/mysql-python/setup.py", line 17, in <module>
        metadata, options = get_config()
      File "setup_posix.py", line 43, in get_config
        libs = mysql_config("libs_r")
      File "setup_posix.py", line 25, in mysql_config
        raise EnvironmentError("%s not found" % (mysql_config.path,))
    EnvironmentError: mysql_config not found
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-WXInHg/mysql-python/
You are using pip version 8.1.1, however version 19.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

需要安装:python-mysqldb

sudo apt-get install python-mysqldb

然后再安装MySQL-Python

(flask) ubantu@ubantu-virtual-machine:~/flask-tutorial$ sudo pip install mysql-python
The directory '/home/ubantu/.cache/pip/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
The directory '/home/ubantu/.cache/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting mysql-python
  Downloading https://files.pythonhosted.org/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip (108kB)
    100% |████████████████████████████████| 112kB 24kB/s 
Installing collected packages: mysql-python
  Running setup.py install for mysql-python ... done
Successfully installed mysql-python-1.2.5
You are using pip version 8.1.1, however version 19.0.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

mysql数据库驱动

python3中使用pymysql作为数据库驱动

import pymysql
pymysql.install_sa_mysqldb()

python2中使用MySQL-Python作为数据库驱动

(2)配置连接信息

  • 设置连接数据库的URL
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://用户名:密码@127.0.0.1:3306/库名'
  • 设置每次请求结束后会自动提交数据库中的改动(官方建议不要使用
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
  • 修改表中数据时,同步修改模型类(建议使用
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
  • 查询时会显示原始SQL语句
# 查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True
  • 创建连接对象
db = SQLAlchemy(app)

(3)常用的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字符串,对较长或不限长度的字符串做了优化
Boolen bool:布尔值
Date datetime.date:时间
Time datetime.datetime:日期和时间
LargeBinary str:二进制文件

(4)常用SQLAlchemy列选项

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

(5)常用的SQLAlchemy关系选项

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

(6)创建数据表:

# coding:utf-8


from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)


# create database db_flask default charset utf8 collate utf8_general_ci;

class Config(object):
    """配置参数"""
    SQLALCHEMY_DATABASE_URL = "myslq://root:[email protected]:3306/db_flask"
    # 设置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)
    # 需要手动添加,方便使用Role.user查询用户对象,user列不是真实存在的,backref="role"为了方便通过User.role获取角色对象,
    # 因为使用User.role_id只能获取到角色id,要想获取角色对象,还需要再在Role表中查询一次
    users = db.relationship("User", backref="role")

	def __repr__(self):
		"""定义之后,可以让显示对象的时候更直观,类似于Django中的__str__"""
		return "Rloe object: name=%s" % self.name

	# In [4]: Role.query.get(1)
	# Out[4]: Rloe object: name=admin

	# In [5]:

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

# In [50]: ro.users
# Out[50]: [<User 2>, <User 4>]

# In [51]:

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), nullable=False)  # nullable=False 参数必须传
    role_id = db.Column(db.Integer, db.ForeignKey("tbl_roles.id"))

# In [53]: usr = User.query.get(1)

# 此处的role是来自于Role表中users字段中定义的backref属性值
# In [54]: usr.role
# Out[54]: <Role 2>

# In [55]: usr.role.name
# Out[55]: u'stuff'

# In [56]: 


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

	usr1 = User(name='zhao', email='[email protected]', password='123456', role_id=role2.id)
	usr2 = User(name='qian', email='[email protected]', password='123456', role_id=role1.id)
	usr3 = User(name='sui', email='[email protected]', password='123456', role_id=role2.id)
	usr4 = User(name='li', email='[email protected]', password='123456', role_id=role1.id)
	# 一次保存多条数据
	db.session.add_all([usr1, usr2, usr3, usr4])
	db.session.commit()

运行程序,创建数据表:

(flask) ubantu@ubantu-virtual-machine:~/flask-tutorial$ python db_demo.py 

在这里插入图片描述
在这里插入图片描述
(7)常用的SQLAlchemy查询执行器

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

(8)查询数据表

  • 查询多条数据:query.all()
In [1]: from db_demo import *

In [2]: Role.query.all()
Out[2]: [<Role 1>, <Role 2>]

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

In [4]: r = lst[0]

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

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

In [7]: 
  • 查询一条数据:query.first()
  • query.get,只能接受主键字段作为查询条件
In [7]: Role.query.first()
Out[7]: <Role 1>

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

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

In [10]:


In [11]: r = Role.query.get(2)

In [12]: r
Out[12]: <Role 2>

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

In [14]: 
  • SQLAlchemy原装查询方式
In [14]: db.session.query(Role).all()
Out[14]: [<Role 1>, <Role 2>]

In [15]: db.session.query(Role).get(2)
Out[15]: <Role 2>

In [16]: db.session.query(Role).first()
Out[16]: <Role 1>

In [17]: 

(9)常用的SQLAlchemy查询过滤器

过滤器 说明
filter 把过滤器添加到原查询上,返回一个新查询结果
filter_by() 把等值过滤器添加到原查询上,返回一个新查询
limit 使用指定的值限定原查询返回的结果
offset () 偏移原查询返回的结果,返回一个新查询
order_by() 根据指定条件对查询结果进行排序,返回一个新查询
group_by() 根据指定条件对查询结果进行分组,返回一个新查询
  • filter_by()
In [17]: User.query.filter_by(name='zhao')
Out[17]: <flask_sqlalchemy.BaseQuery at 0x7f06d4f3ae50>

In [18]: User.query.filter_by(name='zhao').all()
Out[18]: [<User 1>]

In [19]: User.query.filter_by(name='zhao').first()
Out[19]: <User 1>

In [20]: user = User.query.filter_by(name='zhao').first()

In [21]: user.name
Out[21]: u'zhao'

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

In [23]: 
  • filter()
In [27]: user = User.query.filter(User.name=='zhao', User.role_id==2).first()

In [28]: user.name
Out[28]: u'zhao'

In [29]: 

  • 或查寻_or
In [29]: from sqlalchemy import or_

In [30]: user = User.query.filter(or_(User.name=='zhao', User.email.startswith('li'))).all()

In [31]: user
Out[31]: [<User 1>, <User 4>]

In [32]: user[0].name
Out[32]: u'zhao'

In [33]: 
  • 完整查询
User.query.filter().offset().limit().order_by().all()
  • 跳过前两条数据offset(2)
In [35]: lst = User.query.offset(2).all()

In [36]: lst[0].name
Out[36]: u'sui'

In [37]: lst[1].name
Out[37]: u'li'

In [38]: lst
Out[38]: [<User 3>, <User 4>]

In [39]: 

  • 取两条数据limit(2)
In [39]: lst = User.query.offset(1).limit(2).all()

In [40]: lst
Out[40]: [<User 2>, <User 3>]

In [41]: lst[0].name
Out[41]: u'qian'

In [42]: lst[1].name
Out[42]: u'sui'

In [43]:
  • 排序order_by()
In [43]: lst = User.query.order_by(User.id.desc()).all()

In [44]: lst
Out[44]: [<User 4>, <User 3>, <User 2>, <User 1>]

In [45]:
  • 分组group_by()
    在这里插入图片描述
In [46]: from sqlalchemy import func

In [47]: db.session.query(User.role_id, func.count(role_id)).group_by(User.role_id).all()

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

In [49]: 

(10)修改数据

In [8]: usr = User.query.get(1)

In [9]: usr.name
Out[9]: u'zhao'

In [10]: usr.name = "jin"

In [11]: db.session.add(usr)

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

在这里插入图片描述

In [13]: User.query.filter_by(name="qian").update({"name":"yin", "email":"[email protected]"})
Out[13]: 1L

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

In [15]: 

在这里插入图片描述
(11)删除数据

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

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

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

In [19]:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42517220/article/details/88797649