SQLAlchemy最新权威详细教程.docx
- 文档编号:30037536
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:76
- 大小:143.43KB
SQLAlchemy最新权威详细教程.docx
《SQLAlchemy最新权威详细教程.docx》由会员分享,可在线阅读,更多相关《SQLAlchemy最新权威详细教程.docx(76页珍藏版)》请在冰豆网上搜索。
SQLAlchemy最新权威详细教程
SQLAlchemy最新权威详细教程
前言:
最近开始学习SQLAlchemy,本教程是其官方文档以及在读英文版
1什么是SQLAlchemy?
它是给mysql,oracle,sqlite等关系型数据库的python接口,不需要大幅修改原有的python代码,它已经包含了SQL表达式语言和ORM,看一些例子:
sql=”INSERTINTOuser(user_name,password)VALUES(%s,%s)”
cursor=conn.cursor()
cursor.execute(sql,(‘dongwm’,‘testpass’))
以上是一个常用的mysql的SQL语句,但是冗长也容易出错,并且可能导致安全问题(因为是字符串的语句,会存在SQL注入),并且代码不跨平台,在不同数据库软件的语句不同(以下是一个 Oracle例子),不具备客移植性:
sql=”INSERTINTOuser(user_name,password)VALUES(:
1,:
2)”
cursor=conn.cursor()
cursor.execute(sql,‘dongwm’,‘testpass’)
而在SQLAlchemy里只需要这样写:
statement=user_table.insert(user_name=’rick’,password=’parrot’)
statement.execute() #护略是什么数据库环境
SQLAlchemy还能让你写出很pythonic的语句:
statement=user_table.select(and_(
user_table.c.created>=date(2007,1,1),
user_table.c.created result=statement.execute() #检索所有在2007年创建的用户 metadata=MetaData(‘sqlite: //’)#告诉它你设置的数据库类型是基于内存的sqlite user_table=Table( #创建一个表 ‘tf_user’,metadata, Column(‘id’,Integer,primary_key=True), #一些字段,假设你懂SQL,那么以下的字段很好理解 Column(‘user_name’,Unicode(16),unique=True,nullable=False), Column(‘email_address’,Unicode(255),unique=True,nullable=False), Column(‘password’,Unicode(40),nullable=False), Column(‘first_name’,Unicode(255),default=”), Column(‘last_name’,Unicode(255),default=”), Column(‘created’,DateTime,default=datetime.now)) users_table=Table(‘users’,metadata,autoload=True)#假设table已经存在.就不需要指定字段,只是加个autoload=True classUser(object): pass #虽然SQLAlchemy强大,但是插入更新还是需要手动指定,可以使用ORM,方法就是: 设定一个类,定义一个表,把表映射到类里面 mapper(User,user_table) 下面是一个完整ORM的例子: Sourcecode fromsqlalchemy.ormimportmapper,sessionmaker#sessionmaker()函数是最常使用的创建最顶层可用于整个应用Session的方法,Session管理着所有与数据库之间的会话 fromdatetimeimportdatetime fromsqlalchemyimportTable,MetaData,Column,ForeignKey,Integer,String,Unicode,DateTime#会SQL的人能理解这些函数吧? engine=create_engine("sqlite: ///tutorial.db",echo=True)#创建到数据库的连接,echo=True表示用logging输出调试结果 metadata=MetaData()#跟踪表属性 user_table=Table(#创建一个表所需的信息: 字段,表名等 'tf_user',metadata, Column('id',Integer,primary_key=True), Column('user_name',Unicode(16),unique=True,nullable=False), Column('email_address',Unicode(255),unique=True,nullable=False), Column('password',Unicode(40),nullable=False), Column('first_name',Unicode(255),default=''), Column('last_name',Unicode(255),default=''), Column('created',DateTime,default=datetime.now)) metadata.create_all(engine)#在数据库中生成表 classUser(object): pass#创建一个映射类 mapper(User,user_table)#把表映射到类 Session=sessionmaker()#创建了一个自定义了的Session类 Session.configure(bind=engine)#将创建的数据库连接关联到这个session session=Session() u=User() u.user_name='dongwm' u.email_address='dongwm@' u.password='testpass'#给映射类添加以下必要的属性,因为上面创建表指定这几个字段不能为空 session.add(u)#在session中添加内容 session.flush()#保存数据 mit()#数据库事务的提交,sisson自动过期而不需要关闭 query=session.query(User)#query()简单的理解就是select()的支持ORM的替代方法,可以接受任意组合的class/column表达式 printlist(query)#列出所有user printquery.get (1)#根据主键显示 printquery.filter_by(user_name='dongwm').first()#类似于SQL的where,打印其中的第一个 u=query.filter_by(user_name='dongwm').first() u.password='newpass'#修改其密码字段 mit()#提交事务 printquery.get (1).password#打印会出现新密码 forinstanceinsession.query(User).order_by(User.id): #根据id字段排序,打印其中的用户名和邮箱地址 printinstance.user_name,instance.email_address 既然是ORM框架,我们来一个更复杂的包含关系的例子,先看sql语句: CREATETABLEtf_user( idINTEGERNOTNULL, user_nameVARCHAR(16)NOTNULL, email_addressVARCHAR(255)NOTNULL, passwordVARCHAR(40)NOTNULL, first_nameVARCHAR(255), last_nameVARCHAR(255), createdTIMESTAMP, PRIMARYKEY(id), UNIQUE(user_name), UNIQUE(email_address)); CREATETABLEtf_group( idINTEGERNOTNULL, group_nameVARCHAR(16)NOTNULL, PRIMARYKEY(id), UNIQUE(group_name)); CREATETABLEtf_permission( idINTEGERNOTNULL, permission_nameVARCHAR(16)NOTNULL, PRIMARYKEY(id), UNIQUE(permission_name)); CREATETABLEuser_group( user_idINTEGER, group_idINTEGER, PRIMARYKEY(user_id,group_id), FOREIGNKEY(user_id)REFERENCEStf_user(id),#user_group的user_id关联了tf_user的id字段 FOREIGNKEY(group_id)REFERENCEStf_group(id)); #group_id关联了tf_group的id字段 CREATETABLEgroup_permission( group_idINTEGER, permission_idINTEGER, PRIMARYKEY(group_id,permission_id), FOREIGNKEY(group_id)REFERENCEStf_group(id), #group_permission的id关联tf_group的id字段 FOREIGNKEY(permission_id)REFERENCEStf_permission(id));#permission_id关联了tf_permission的id字段 这是一个复杂的多对多的关系,比如检查用户是否有admin权限,sql需要这样: SELECTCOUNT(*)FROMtf_user,tf_group,tf_permissionWHERE tf_user.user_name=’dongwm’ANDtf_user.id=user_group.user_id ANDuser_group.group_id=group_permission.group_id ANDgroup_permission.permission_id=tf_permission.id ANDpermission_name=’admin’; 看起来太复杂并且繁长了 在面向对象的世界里,是这样的: classUser(object): groups=[] classGroup(object): users=[] permissions=[] classPermission(object): groups=[] Sourcecode print'Summaryfor%s'%user.user_name forginuser.groups: print'Memberofgroup%s'%g.group_name forping.permissions: print'...whichhaspermission%s'%p.permission_name Sourcecode defuser_has_permission(user,permission_name): #检查用户是否有permission_name的权限的函数 forginuser.groups: forping.permissions: #可以看出来使用了for循环 ifp.permission_name=='admin': returnTrue returnFalse 而在SQLAlchemy中,这样做: mapper(User,user_table,properties=dict( groups=relation(Group,secondary=user_group,backref=’users’)))#properties是一个字典值。 增加了一个groups值,它又是一个relation对象,这个对象实现 #了Group类与user_group的 映射。 这样我通过user_table的groups属性就可以反映出RssFeed的值来, #中间表对象(user_group)传给secondary参数,backref为自己的表(users) mapper(Group,group_table,properties=dict( permissions=relation(Permission,secondary=group_permission, backref=’groups’))) mapper(Permission,permission_table) q=session.query(Permission) dongwm_is_admin=q.count_by(permission_name=’admin’,user_name=’dongwm’) 假如计算组里用户数(不包含忘记删除但是重复的) forpinpermissions: users=set() forginp.groups: foruing.users: users.add(u) print‘Permission%shas%dusers’%(p.permission_name,len(users)) 在SQLAlchemy可以这样: q=select([Permission.c.permission_name, func.count(user_group.c.user_id)], and_(Permission.c.id==group_permission.c.permission_id, Group.c.id==group_permission.c.group_id, Group.c.id==user_group.c.group_id), group_by=[Permission.c.permission_name], distinct=True) rs=q.execute() forpermission_name,num_usersinq.execute(): print‘Permission%shas%dusers’%(permission_name,num_users)#虽然也长,但是减少了数据库查询次数,也就是让简单事情简单化,复杂事情可能简单解决 看一个综合的例子: classUser(object): #这些类设计数据库的模型 def__init__(self,group_name=None,users=None,permissions=None): ifusersisNone: users=[] ifpermissionsisNone: permissions=[] self.group_name=group_name self._users=users self._permissions=permissions defadd_user(self,user): self._users.append(user) defdel_user(self,user): self._users.remove(user) defadd_permission(self,permission): self._permissions.append(permission) defdel_permission(self,permission): self._permissions.remove(permission) classPermission(object): def__init__(self,permission_name=None,groups=None): self.permission_name=permission_name self._groups=groups defjoin_group(self,group): self._groups.append(group) defleave_group(self,group): self._groups.remove(group) 用sqlalchemy的效果是这样的: user_table=Table( ‘tf_user’,metadata, Column(‘id’,Integer,primary_key=True), Column(‘user_name’,Unicode(16),unique=True,nullable=False), Column(‘password’,Unicode(40),nullable=False)) group_table=Table( ‘tf_group’,metadata, Column(‘id’,Integer,primary_key=True), Column(‘group_name’,Unicode(16),unique=True,nullable=False)) permission_table=Table( ‘tf_permission’,metadata, Column(‘id’,Integer,primary_key=True), Column(‘permission_name’,Unicode(16),unique=True, nullable=False)) user_group=Table( ‘user_group’, metadata, Column(‘user_id’,None,ForeignKey(‘tf_user.id’), primary_key=True), Column(‘group_id’,None,ForeignKey(‘tf_group.id’), primary_key=True)) group_permission=Table( ‘group_permission’, metadata, Column(‘group_id’,None,ForeignKey(‘tf_group.id’), primary_key=True), Column(‘permission_id’,None,ForeignKey(‘tf_permission.id’), primary_key=True)) mapper(User,user_table,properties=dict( _groups=relation(Group,secondary=user_group,backref=’_users’))) mapper(Group,group_table,properties=dict( _permissions=relation(Permission,secondary=group_permission, backref=_’groups’))) mapper(Permission,permission_table) 这里没有修改对象,而join_group,leave_group这样的函数依然可用,sqlalchemy会跟踪变化,并且自动刷新数据库 上面介绍了一个完整的例子,连接数据库嗨可以这样: engine=create_engine(‘sqlite: //’) connection=engine.connect() #使用connect result=connection.execute(“selectuser_namefromtf_user”) forrowinresult: print‘username: %s’%row['user_name'] result.close() engine=create_engine(‘sqlite: //’,strategy=’threadlocal’) #,strategy=’threadlocal’表示重用其它本地线程减少对数据库的访问 fromsqlalchemy.databases.mysqlimportMSEnum,MSBigInteger #这个sqlalchemy.databases是某数据库软件的’方言’集合,只支持特定平台 user_table=Table(‘tf_user’,meta, Column(‘id’,MSBigInteger), Column(‘honorific’,MSEnum(‘Mr’,‘Mrs’,‘Ms’,‘Miss’,‘Dr’,‘Prof’))) 以下是几个MetaData的应用: unbound_meta=MetaData() #这个metadata没有绑定 db1=create_engine(‘sqlite: //’) unbound_meta.bind=db1 #关联引擎 db2=MetaData(‘sqlite: ///test1.db’) #直接设置引擎 bound_meta1=MetaData(db2) #CreateaboundMetaDatawithanimplicitlycreatedengine bound_meta2=MetaData(‘sqlite: ///test2.db’) #隐式绑定引擎 meta=MetaData(‘sqlite: //’)#直接绑定引擎可以让源数据直接访问数据库 user_table=Table( ‘tf_user’,meta, Column(‘id’,Integer,primary_key=True), Column(‘user_name’,Unicode(16),unique=True,nullable=False), Column(‘password’,Unicode(40),nullable=False))
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SQLAlchemy 最新 权威 详细 教程