盘点Flask与数据库的交互插件--Flask-Sqlalchemy

运维 数据库运维
在我们做web开发的时候,经常需要用到与数据库交互,因为我们的数据通常都是保存在数据库中的,如果有人需要访问,就必须与数据库访问,所以今天我们介绍一个Flask中与数据库交互的插件---Flask-Sqlalchemy。

[[418400]]

大家好,我是Python进阶者。

前言

在我们做web开发的时候,经常需要用到与数据库交互,因为我们的数据通常都是保存在数据库中的,如果有人需要访问,就必须与数据库访问,所以今天我们介绍一个Flask中与数据库交互的插件---Flask-Sqlalchemy。

一、安装并导入

  1. pip install flask-sqlalchemy 
  2.  
  3. from flask_sqlalchemy import SQLAlchemy 
  4. import os 
  5. import pymysql as p 
  6. from flask import Flask 

二、基本用法

今天我们要了解的是Mysql数据库,所以这里重点介绍连接Mysql数据库的方法。

1.连接数据库

1).写在配置文件中然后读取

首先创建一个配置文件"config.py",内容为:

  1. db_type='mysql' 
  2. db_conn='pymysql' 
  3. host='127.0.0.1' 
  4. username='root' 
  5. password='123456' 
  6. port='3306' 
  7. db_name='people' 
  8. SQLALCHEMY_DATABASE_URI='{}+{}://{}:{}@{}:{}/{}?charset=utf8'.format(db_type,db_conn,username,password,host,port,db_name) 
  9. SQLALCHEMY_COMMIT_ON_TEARDOWN=False 
  10. SQLALCHEMY_TRACK_MODIFICATIONS=True 

然后在应用中导入配置文件:

  1. from flask_sqlalchemy import SQLAlchemy 
  2. from flask import Flask 
  3. import config 
  4. app=Flask(__name__) 
  5. app.config.from_object(config) # 连接数据库配置文件 
  6. db=SQLAlchemy(app) 
  7. db.create_all()  # 创建所有的数据库 

2).直接写在应用中读取

  1. app=Flask(__name__) 
  2. p.install_as_MySQLdb()   # mysql连接器,因为不支持py3版本,所以必须加上这行 
  3. app.config['SECRET_KEY']=os.urandom(50) 
  4. app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://root:123456@127.0.0.1:3306/people' 
  5. app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True   # 每次请求结束后都会自动提交数据库中的变动 
  6. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True  # 动态追踪修改设置,如未设置只会提示警告 
  7. db = SQLAlchemy(app) 

还有许多其它的配置参数,比如:

  1. SQLALCHEMY_NATIVE_UNICODE    # 可以用于显式禁用原生 unicode 支持 
  2. SQLALCHEMY_POOL_SIZE         # 数据库连接池的大小,默认是引擎默认值(5)  
  3. SQLALCHEMY_POOL_TIMEOUT      # 设定连接池的连接超时时间,默认是 10 
  4. SQLALCHEMY_POOL_RECYCLE      # 多少秒后自动回收连接,mysql默认为2小时 
  5. SQLALCHEMY_RECORD_QUERIES    # 可以用于显式地禁用或启用查询记录 
  6. SQLALCHEMY_ECHO              # 为Ture时用于调试,显示错误信息 
  7. SQLALCHEMY_BINDS             # 一个映射 binds 到连接 URI 的字典 

3).使用独特的创建引擎

  1. from sqlalchemy import create_engine 
  2. # echo参数为True时,会显示每条执行的SQL语句,为False时关闭 
  3. engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/people',echo=True
  4. engine.connect() 

这样我们就算与People数据库建立连接了,接下来我们来建立一张表。

4).创建连接多个数据库

  1. app.config['SQLALCHEMY_BINDS']={ 
  2. 'users'"mysql+pymysql://root:123456@127.0.0.1:3306/user"
  3.     'admin''sqlite://C:/Users/Administrator/Desktop/admin'
  4.     'buy':   'postgresql://root:123321@127.0.0.1/buy' 

然后引用表:

  1. db.create_all(bind=['users']) 
  2. db.create_all(bind='admin'

指定Users数据库中的表:

  1. __bind_key__ = 'users' 
  2. bind key 内部存储在表的 info 字典中  即:info={'bind_key''users'

2.建立数据表并插入值

1).继承"db.Model"类

  1. from flask_sqlalchemy import SQLAlchemy 
  2. from flask import Flask 
  3. import config 
  4. app=Flask(__name__) 
  5. app.config.from_object(config) # 添加配置文件 
  6. db=SQLAlchemy(app) 
  7. class User(db.Model): 
  8.     __tablename__='users' 
  9.     id=db.Column(db.Integer, primary_key=True,autoincrement=True) # 整数类型的自增主键 
  10.     username=db.Column(db.String(100),nullable=False)  # 字符类型不为空 
  11.     password=db.Column(db.String(100),nullable=False)  # 字符类型不为空 
  12.  
  13.     def __init__(self,username,password): 
  14.         self.username=username 
  15.         self.password=password 
  16.  
  17.     def __repr__(self): 
  18.         # 打印当前类名和它的实例化后的值 
  19.         return ' %s is %r' %(self.__class__.__name__,self.username)  
  20.      
  21.      
  22. # 请求钩子,第一次请求之前执行 
  23. @app.before_first_request 
  24. def create_table():  
  25.     db.drop_all()  # 删除所有表 
  26.     db.create_all() # 创建新的表 
  27.  
  28.      
  29. @app.route('/'
  30. def create(): 
  31.     use1= User('hwhrr''123321')   
  32.     use2= User('hwzjj''123456'
  33.     use3= User('hwzzz''654321'
  34.     db.session.add_all([use1,use2,use3]) # 添加所有的用户,添加一个用户去掉_all后面加一个元祖即可  
  35.     db.session.commit()  # 提交数据 
  36.     return use1.__repr__() # 返回用户1的值 
  37.  
  38. if __name__ == '__main__':   
  39.     app.run(debug=True

  1. Column        参数列表   
  2. name          列名 
  3. type_         类型 
  4. *args         列表参数 
  5. Constraint(约束), ForeignKey(外键), ColumnDefault(默认), Sequenceobjects(序列)定义 
  6. key         列名的别名 
  7. primary_key 如果为True,则是主键 
  8. nullable    如果是True,则可以为null 
  9. default     设置默认值,默认是None 
  10. index       是否是索引,默认是True 
  11. unique      是否唯一键,默认是False 
  12. onupdate    指定一个更新时候的值 
  13. autoincrement 设置为整型自动增长 
  14. quote         如果列明是关键字,则强制转义,默认False 

2).利用原始引擎来创建会话(稍微复杂点)

  1. from flask import Flask 
  2. from sqlalchemy import create_engine 
  3. from sqlalchemy.orm import sessionmaker 
  4. from sqlalchemy.ext.declarative import declarative_base 
  5. from sqlalchemy import ColumnInteger, String 
  6. app=Flask(__name__) 
  7. Base = declarative_base() 
  8. # 创建连接数据库的引擎并且打开回显 
  9. engine = create_engine("mysql+pymysql://root:123456@localhost/people",echo=True
  10. Session = sessionmaker(bind=engine) # 创建会话标记 
  11. class User(Base): 
  12.     __tablename__ = 'article' 
  13.     id = Column(Integer, primary_key=True,autoincrement=True
  14.     username = Column(String(100),nullable=False
  15.     password = Column(String(100),nullable=False
  16.     def __init__(self, username,password): 
  17.         self.username = username 
  18.         self.password=password 
  19.     def __repr__(self): 
  20.         return ' %s is %r' %(self.__class__.__name__,self.username) 
  21.      
  22. @app.before_first_request 
  23. def create_table(): 
  24.     Base.metadata.drop_all(engine) # 删除所有数据库 
  25.     Base.metadata.create_all(engine) # 创建所有数据库 
  26.      
  27. @app.route('/'
  28. def index(): 
  29.     userUser("hwhrr","123321"
  30.     session = Session()   # 创建会话 
  31.     session.add(user)  # 添加内容 
  32.     session.commit()  # 提交 
  33.     return user.__repr__() 
  34.  
  35. if __name__ == '__main__':   
  36.     app.run(debug=True

3.数据库之间的关系

1). 一对一

只需让两张表都在同等的位置上,属于双向关系。

  1. class father(db.Model): 
  2.     __tablename__='Father' 
  3.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  4.     name= db.Column(db.String(100),nullable=False
  5.     age= db.Column(db.Integer,nullable=False
  6.     #主要是要在一个表上设置uselist 然后设置back_populates的值为其它表的映射返回值 
  7.     son_fa=db.relationship('son',uselist=False, back_populates='fa_son')  
  8.     def __init__(self,name,age): 
  9.         self.name=name 
  10.         self.age=age 
  11.     def __repr__(self): 
  12.         return '%s is %r'%(self.__class__.__name__,self.name
  13.  
  14.  
  15. class son(db.Model): 
  16.     __tablename__='Son' 
  17.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  18.     name= db.Column(db.String(100),nullable=False
  19.     age= db.Column(db.Integer,nullable=False
  20.     # 这里无需设置uselist 
  21.     fa_son=db.relationship('father',back_populates='son_fa'
  22.     def __init__(self,name,age): 
  23.         self.name=name 
  24.         self.age=age 
  25.     def __repr__(self): 
  26.         return '%s is %r'%(self.__class__.__name__,self.name

2).一对多

我们需要建立一个主表和一个子表,分别命名为“father”和‘son’,然后需要建立外键和反射来互相引用建立一种关系,我们来看看:

  1. class father(db.Model): 
  2.     __tablename__='Father' 
  3.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  4.     name= db.Column(db.String(100),nullable=False
  5.     age= db.Column(db.Integer,nullable=False
  6.     # 表示另一端是son这个模型,backref可替代Father.id访问father模型 
  7.     son_fa=db.relationship('son',backref='fa',lazy='dynamic'
  8.     # lazy表示加载方式: 
  9.     # dynamic:动态加载,只有用到了才加载 只可以用在一对多和多对多关系中 
  10.     # subquery:全部加载 
  11.     def __init__(self,name,age): 
  12.         self.name=name 
  13.         self.age=age 
  14.     def __repr__(self): 
  15.         return '%s is %r'%(self.__class__.__name__,self.name
  16.  
  17.  
  18. class son(db.Model): 
  19.     __tablename__='Son' 
  20.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  21.     name= db.Column(db.String(100),nullable=False
  22.     age= db.Column(db.Integer,nullable=False
  23.     f_id=db.Column(db.Integer,db.ForeignKey('Father.id')) # 建立外键关联,指明表名和字段 
  24.     def __init__(self,name,age): 
  25.         self.name=name 
  26.         self.age=age         
  27.     def __repr__(self): 
  28.         return '%s is %r'%(self._class__.__name__,self.name
  29.  
  30. @app.route('/'
  31. def create(): 
  32.     use1= father('hw', 45) 
  33.     use2= son('hyy', 20) 
  34.     db.session.add_all([use1,use2]) 
  35.     db.session.commit() 
  36.     return use1.__repr__()+'\n'+use2.__repr__() 

3).多对一

就是将反射应用在子表上,与父表同时进行关联。

  1. class father(db.Model): 
  2.     __tablename__='Father' 
  3.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  4.     name= db.Column(db.String(100),nullable=False
  5.     age= db.Column(db.Integer,nullable=False
  6.     # 表示另一端是son这个模型 
  7.     son_fa=db.relationship('son', back_populates="fath")  
  8.     def __init__(self,name,age): 
  9.         self.name=name 
  10.         self.age=age 
  11.     def __repr__(self): 
  12.         return '%s is %r'%(self.__class__.__name__,self.name
  13.  
  14.  
  15. class son(db.Model): 
  16.     __tablename__='Son' 
  17.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  18.     name= db.Column(db.String(100),nullable=False
  19.     age= db.Column(db.Integer,nullable=False
  20.     f_id=db.Column(db.Integer,db.ForeignKey('Father.id')) # 建立外键关联 
  21.     # 表示另一端是father这个模型 
  22.     fa_son=db.relationship('father',back_populates="so")  
  23.     def __init__(self,name,age): 
  24.         self.name=name 
  25.         self.age=age 
  26.     def __repr__(self): 
  27.         return '%s is %r'%(self.__class__.__name__,self.name

4).多对多

设置一个关联表来对两个表同时进行管理。

  1. # 设置关联表 
  2. gl=db.Table('glb'
  3.     db.Column('id',db.Integer,primary_key=True,autoincrement=True), 
  4.     db.Column('son_id',db.Integer,db.ForeignKey('Son.id')), 
  5.     db.Column('father_id',db.Integer,db.ForeignKey('Father.id')) 
  6.  
  7. # 父表 
  8. class father(db.Model): 
  9.     __tablename__='Father' 
  10.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  11.     name= db.Column(db.String(100),nullable=False
  12.     age= db.Column(db.Integer,nullable=False
  13.     # 设置关联表 动态加载 
  14.     son_fa=db.relationship('son',secondary=gl,backref="fas",lazy="dynamic"
  15.     def __init__(self,name,age): 
  16.         self.name=name 
  17.         self.age=age 
  18.     def __repr__(self): 
  19.         return '%s is %r'%(self.__class__.__name__,self.name
  20.  
  21. # 子表 
  22. class son(db.Model): 
  23.     __tablename__='Son' 
  24.     id=db.Column(db.Integer, primary_key=True,autoincrement=True
  25.     name= db.Column(db.String(100),nullable=False
  26.     age= db.Column(db.Integer,nullable=False
  27.     def __init__(self,name,age): 
  28.         self.name=name 
  29.         self.age=age 
  30.     def __repr__(self): 
  31.         return '%s is %r'%(self.__class__.__name__,self.name

可以看出我们已经创建出了一张关联表,名字就是我们设置的“glb”。

4.查看数据

1).查看全部数据(all)

  1. father.query.all() 

2).精准查询(filter_by)

  1. father.query.filter_by(name='hw').all()  # 查找所有名字为hw的记录 

3).模糊查询(filter)

  1. father.query.filter(father.name.startswith('h').all() # 查找所有名字首字母为h的记录 

4).主键查询(get)

  1. father.query.get(1) # 查看id为1的记录 

5).取反操作(not_)

  1. from sqlalchemy import not_ 
  2. father.query.filter(not_(father.name=='hw')).all() # 查找所有除了名字不是hw的记录 

6).与操作(and_)

  1. from sqlalchemy import and_ 
  2. # 查找名字末尾是h并且年龄等于50的记录 
  3. father.query.filter(and_(father.name.endswith('h'),father.age==50)).all() 

7).或操作(or_)

  1. from sqlalchemy import or_ 
  2. # 查找名字末尾是h或者年龄等于50的记录 
  3. father.query.filter(or_(father.name.endswith('h'),father.age==50)).all() 

8).一对多正向查询

  1. son.query.filter_by(f_id=2).all() 

9).一对多反向查询

  1. son.query.filter_by(fa=use1).all() 

10).查询第一个出现的数据

  1. son.query.filter(son.age==10).first() 
  2. son.query.filter(son.age==10)[0] 

11).查询对象并返回指定数量的结果

  1. son.query.filter(son.age==10).limit(10).all() # 返回十个查找到的对象 

12).查询时指定偏移量

  1. son.query.filter(son.age==10).offset(2).all() # 返回偏移了2的对象 

13).查找对象并排序

  1. son.query.filter(son.age==10).order_by(son.create_time.desc()).all() # 返回按降序排序的记录 

14).查找对象返回分组结果

  1. son.query.filter(son.age==10).group_by(son.name).all() # 返回age为10的名字对象分组 

15).返回查询结果的数量

  1. son.query.filter(son.age==10).count() # son的年龄为10的数量 

16).返回切片结果

  1. son.query(son).slice(10,40).all()   # son从10到40的记录 
  2. son.query(son)[10:40] 

17).分页获取数据

  1. p=request.args.get('p'
  2. # 从请求的查询字符串中获取当前页面,返回一个每页显示3条记录的分页对象 
  3. paginate=son.query.paginate(p=int(p),per_page=3)  
  4. paginate 属性: 
  5. pages     # 总共生成页面数量 
  6. page      # 当前页数 
  7. has_next  # 判断是否有下一页 
  8. has_prev  # 判断是否有上一页 
  9. next_num  # 获取下一页的页码数 
  10. prev_num  # 获取上一页的页码数 
  11. items     # 获取当前页的记录 
  12. total     # 查询返回的记录总数 

18).查询仅显示一条记录

  1. son.query(son).one() 

5.更新数据

  1. ss=son.query.get(1) 
  2. ss.name='fasd'     # 更改name的值来达到更新的目的 
  3. db.session.commit() 

6.删除数据

  1. ss=son.query.get(1) 
  2. db.session.delete(ss) 
  3. db.session.commit() 

三、总结

Sqlalchemy支持很多表的建立和操作,通过对它的了解,我们可以很方便的操作数据库的数据从而与前端页面交互达到可视化的效果,通过这篇文章的学习,相信你可以独立开发一个小网站了。

本文转载自微信公众号「Python爬虫与数据挖掘」,可以通过以下二维码关注。转载本文请联系Python爬虫与数据挖掘公众号。

 

责任编辑:武晓燕 来源: Python爬虫与数据挖掘
相关推荐

2016-11-08 10:24:37

FlaskPython插件

2023-06-08 08:13:43

2023-06-07 08:18:25

2021-09-12 17:25:12

SQLite数据库

2023-06-09 07:55:09

2014-12-29 10:29:40

OpenStack数据库SQLAlchem

2015-01-12 15:07:56

SQLAlchemy数据库开发OpenStac

2022-03-16 00:15:56

Flask扩展插件

2021-06-26 10:03:35

Python框架Flask

2021-07-01 09:08:03

Python网页开发Flask

2016-09-23 13:34:15

PythonORMsqlalchemy

2024-10-30 15:53:59

2021-11-26 22:51:31

FlaskBlueprintsViews

2024-04-03 10:05:02

2009-09-11 10:48:25

数据库交互

2022-01-03 18:15:35

FlaskTepHttpRunner

2022-08-31 15:09:03

PythonOthers

2010-06-11 16:51:44

MySQL数据库

2010-06-12 14:40:28

2023-05-27 21:13:34

FlaskURL装饰器
点赞
收藏

51CTO技术栈公众号