文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-12-02 23:52

关注

大家好,我是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爬虫与数据挖掘内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯