大家好,我是Python进阶。前言我们在做web开发的时候,经常需要和数据库进行交互,因为我们的数据通常都保存在数据库中,如果有人需要访问,就必须访问数据库,所以今天介绍一个Flask和数据库交互的插件——-Flask-Sqlalchemy。1.安装并导入pipinstallflask-sqlalchemyfromflask_sqlalchemyimportSQLAlchemyimportosimportpymysqlaspfromflaskiimportFlask2。基本使用今天我们需要了解Mysql数据库,所以这里重点介绍连接Mysql数据库的方法。1.连接数据库1).写入配置文件然后读取首先创建一个配置文件“config.py”,内容为:db_type='mysql'db_conn='pymysql'host='127.0.0.1'username='root'password='123456'port='3306'db_name='people'SQLALCHEMY_DATABASE_URI='{}+{}://{}:{}@{}:{}/{}?charset=utf8'.format(db_type,db_conn,username,password,host,port,db_name)SQLALCHEMY_COMMIT_ON_TEARDOWN=FalseSQLALCHEMY_TRACK_MODIFICATIONS=True然后在应用中导入配置文件:fromflask_sqlalchemyimportSQLAlchemyfromflaskimportFlaskimportconfigapp=Flask(__name__)app.config.from_object(db=config)#连接数据库配置文件create_all()#创建所有数据库2).直接在application中写入读取app=Flask(__name__)p.install_as_MySQLdb()#mysqlconnector,因为不支持py3版本,所以这行app必须加上.config['SECRET_KEY']=os.urandom(50)app.config['SQLALCHEMY_DATABASE_URI']='mysql+pymysql://root:123456@127.0.0.1:3306/people'app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True#数据库的变化会自动每次请求结束后提交app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True#动态跟踪修改设置,如果不设置,只会提示警告db=SQLAlchemy(app)还有很多其他配置参数,比如:SQLALCHEMY_NATIVE_UNICODE#即可用于显式禁用本机unicode支持SQLALCHEMY_POOL_SIZE#数据库连接池的大小,默认为引擎的默认值(5)SQLALCHEMY_POOL_TIMEOUT#设置连接池的连接超时时间,默认为10SQLALCHEMY_POOL_RECYCLE#多少秒自动回收连接,mysql默认为2小时SQLALCHEMY_RECORD_QUERIES#可用于显式禁用或启用查询记录SQLALCHEMY_ECHO#为True时用于调试,显示错误信息SQLALCHEMY_BINDS#AdictionarythatmapsbindstoconnectionURI3).使用独特的创建引擎fromsqlalchemyimportcreate_engine#Echo参数为True,每一项都会显示ExecutedSQLstatement,closeengine=create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/people',echo=True)engine.connect()当它为False时,以便我们可以与People数据库建立连接现在,让我们创建一个表4).创建并连接多个数据库app.config['SQLALCHEMY_BINDS']={'users':"mysql+pymysql://root:123456@127.0.0.1:3306/user",'admin':'sqlite://C:/Users/Administrator/Desktop/admin','buy':'postgresql://root:123321@127.0.0.1/buy'}然后引用表:db.create_all(bind=['users'])db.create_all(bind='admin')指定Users数据库中的表:__bind_key__='users'bindkey内部存储在表的info字典中:info={'bind_key':'users'}2.创建数据表并插入值1)。Inherit"db.Model"classfromflask_sqlalchemyimportSQLAlchemyfromflaskimportFlaskimportconfigapp=Flask(__name__)app.config.from_object(config)#添加配置文件db=SQLAlchemy(app)classUser(db.Model):__tablename__='users'id=db.Column(db.Integer,primary_key=True,autoincrement=True)#整数类型自增主键username=db.Column(db.String(100),nullable=False)#字符类型不为空password=db.Column(db.String(100),nullable=False)#字符类型不为空def__init__(self,username,password):self.username=usernameself.password=passworddef__repr__(self):#打印当前类名及其实例化的值ofreturn'%sis%r'%(self.__class__.__name__,self.username)#请求钩子,在第一次请求前执行@app.before_first_requestdefcreate_table():db.drop_all()#删除所有表db.create_all()#新建表@app.route('/')defcreate():use1=User('hwhrr','123321')use2=User('hwzjj','123456')use3=User('hwzzz','654321')db.session.add_all([use1,use2,use3])#添加所有用户,添加一个用户去掉_all加一个ancestor就够了db.session.commit()#提交数据returnuse1.__repr__()#返回用户1的值if__name__=='__main__':app.run(debug=True)Columnparameterlistnamecolumnnametype_type*argslist参数Constraint(约束)、ForeignKey(外键)、ColumnDefault(默认)、Sequenceobjects(序列)定义键列名的别名primary_key如果为True,则为主键nullable如果为True,则可以设置默认值为nulldefault,默认为Noneindex是否为索引,默认为Trueunique是否为唯一键,默认为Falseonupdate,指定一个更新值,autoincrement设置为整型自动增长引号,如果为关键字,它必须进行转义,默认为False2)。使用原有引擎创建session(稍微复杂一点)fromflaskiimportFlaskfromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportsessionmakerfromsqlalchemy.ext.declarativeimportdeclarative_basefromsqlalchemyimportColumn,Integer,Stringapp=Flask(__name__)Base=declarative_base()#创建引擎连接数据库,打开echo+mysqlengine=create_engine("://mysqlroot:123456@loc??alhost/people",echo=True)Session=sessionmaker(bind=engine)#创建会话标记classUser(Base):__tablename__='article'id=Column(Integer,primary_key=True,autoincrement=True)username=Column(String(100),nullable=False)password=Column(String(100),nullable=False)def__init__(self,username,password):self.username=usernameself.password=passworddef__repr__(self):return'%sis%r'%(self.__class__.__name__,self.username)@app.before_first_requestdefcreate_table():Base.metadata.drop_all(engine)#删除所有数据库Base.metadata.create_all(engine)#创建所有数据库@app.route('/')defindex():user=User("hwhrr","123321")session=Session()#创建会话session.add(user)#添加内容session.commit()#提交returnuser.__repr__()if__name__=='__main__':app.run(debug=True)3.数据库之间的关系1).一对一只需要有两个表在同一个位置,就是双向关系classfather(db.Model):__tablename__='Father'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)#主要是在一个表上设置uselist,然后将back_populates的值设置为其他表的映射返回值son_fa=db.relationship('son',uselist=False,back_populates='fa_son')def__init__(self,name,age):self.name=nameself.age=agedef__repr__(self):return'%sis%r'%(self.__class__.__name__,self.name)classson(db.Model):__tablename__='Son'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)#不用设置uselistfa_son=db.relationship('father',back_populates='son_fa')def__init__(self,name,age):self.name=nameself.age=agedef__repr__(self):return'%sis%r'%(self.__class__.__name__,self.name)2).一对多我们需要创建一个主表和一个子表,分别命名为“father”和“son”,然后我们需要创建外键和Reflection来相互引用建立关系,我们来看看:classfather(db.Model):__tablename__='Father'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)#表示另一端是子model,backref可以代替Father.id访问父模型son_fa=db.relationship('son',backref='fa',lazy='dynamic')#lazy表示加载方式:#dynamic:动态加载,只加载用于一对多和多对多关系时#subquery:loadalldef__init__(self,name,age):self.name=nameself.age=agedef__repr__(self):return'%sis%r'%(self.__class__.__name__,self.name)classson(db.Model):__tablename__='Son'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)f_id=db.Column(db.Integer,db.ForeignKey('Father.id'))#建立外键关联,指定表名和字段def__init__(self,name,age):self.name=nameself.age=agedef__repr__(self):return'%sis%r'%(self._class__.__name__,self.name)@app.route('/')defcreate():use1=father('hw',45)use2=son('hyy',20)db.session.add_all([use1,use2])db.session.commit()返回use1.__repr__()+'\n'+use2.__repr__()3)。多对一就是在父表的同时对子表应用反射关联类father(db.Model):__tablename__='Father'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)#表示另一端是儿子模型son_fa=db.relationship('son',back_populates="fath")def__init__(self,name,age):self.name=nameself.age=agedef__repr__(self):返回'%sis%r'%(self.__class__.__name__,self.name)classson(db.Model):__tablename__='Son'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)f_id=db.Column(db.Integer,db.ForeignKey('Father.id'))#建立外键关联#表示另一端是父亲的模型fa_son=db.relationship('father',back_populates="so")def__init__(self,name,age):自己。name=nameself.age=agedef__repr__(self):return'%sis%r'%(self.__class__.__name__,self.name)4).多对多设置一个关联表同时管理两个表。#设置关联表gl=db.Table('glb',db.Column('id',db.Integer,primary_key=True,autoincrement=True),db.Column('son_id',db.Integer,db.ForeignKey('Son.id')),db.Column('father_id',db.Integer,db.ForeignKey('Father.id')))#parenttableclassfather(db.Model):__tablename__='Father'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)#Set关联表动态加载son_fa=db.relationship('son',secondary=gl,backref="fas",lazy="dynamic")def__init__(self,name,age):self.name=nameself.age=agedef__repr__(self):return'%sis%r'%(self.__class__.__name__,self.name)#subtableclassson(db.Model):__tablename__='Son'id=db.Column(db.Integer,primary_key=True,autoincrement=True)name=db.Column(db.String(100),nullable=False)age=db.Column(db.Integer,nullable=False)def__init__(self,name,age):self.name=nameself.age=agedef__repr__(self):return'%sis%r'%(self.__class__.__name__,self.name)可以看出我们创建了一个关联表,名称是我们设置的“gl”b”4.查看数据1).查看所有数据(all)father.query.all()2).精确查询(filter_by)father.query.filter_by(name='hw').all()#查找所有名字为hw3).模糊查询(filter)father.query.filter(father.name.startswith('h'.all()#查找首字母为h的所有记录4).主键查询(get)father.query.get(1)#查看id为1的记录5).逆向操作(not_)fromsqlalchemyimportnot_father.query.filter(not_(father.name=='hw')).all()#查找除名字hw以外的所有记录6).AND运算(and_)fromsqlalchemyimportand_#查找名字以h结尾年龄等于50的记录father.query.filter(and_(father.name.endswith('h'),father.age==50)).all()7).Or操作(or_)fromsqlalchemyimportor_#查找名字以h结尾或者年龄等于50的记录father.query.filter(or_(father.name.endswith('h'),father.age==50)).all()8).一对多正向查询son.query.filter_by(f_id=2).all()9)。一对多反向查询son.query.filter_by(fa=use1)。所有()10)。查询数据第一次出现的son.query.filter(son.age==10).first()son.query.filter(son.age==10)[0]11).Query对象并返回指定次数resultsson.query.filter(son.age==10).limit(10).all()#返回十个找到的对象12)。查询时指定偏移量son.query。filter(son.age==10).offset(2).all()#返回对象偏移213)。找到对象并排序son.query.filter(son.age==10).order_by(son.create_time.desc()).all()#返回按降序排列的记录14).Findobjectreturnsgroupedresultsson.query.filter(son.age==10).group_by(son.name).all()#返回年龄为1015)的name对象分组。返回查询结果的个数son.query.filter(son.age==10).count()#年龄为1016)的儿子个数。返回切片结果son.query(son).slice(10,40).all()#son记录从10到40son.query(son)[10:40]17)。分页获取数据p=request.args.get('p')#从请求的查询字符串中获取当前页,返回一个分页对象,每页显示3条记录paginate=son.query.paginate(p=int(p),per_page=3)paginate属性:pages#总代页数page#当前页码has_next#判断是否有下一页has_prev#判断是否有上一页next_num#获取下一页的页码prev_num#获取上一页item的页码#获取当前页的记录total#查询返回的记录总数18).查询只显示一条记录son.query(son).one()5.更新数据ss=son.query.get(1)ss.name='fasd'#将name的值改为以达到更新的目的db.session.commit()6.删除数据ss=son.query.get(1)db.session.delete(ss)db.session.commit()3.总结Sqlalchemy支持对很多表的建立和处理操作,通过对它的了解,我们可以很方便的操作数据库中的数据与前端页面进行交互,达到可视化的效果。通过本文的学习,相信你可以独立开发一个小型网站。本文转载自微信公众号《Python爬虫与数据挖掘》可通过以下二维码关注。转载本文请联系Python爬虫与数据挖掘公众号。
