SQLAlchemy最新权威详细教程.docx

上传人:b****8 文档编号:30037536 上传时间:2023-08-04 格式:DOCX 页数:76 大小:143.43KB
下载 相关 举报
SQLAlchemy最新权威详细教程.docx_第1页
第1页 / 共76页
SQLAlchemy最新权威详细教程.docx_第2页
第2页 / 共76页
SQLAlchemy最新权威详细教程.docx_第3页
第3页 / 共76页
SQLAlchemy最新权威详细教程.docx_第4页
第4页 / 共76页
SQLAlchemy最新权威详细教程.docx_第5页
第5页 / 共76页
点击查看更多>>
下载资源
资源描述

SQLAlchemy最新权威详细教程.docx

《SQLAlchemy最新权威详细教程.docx》由会员分享,可在线阅读,更多相关《SQLAlchemy最新权威详细教程.docx(76页珍藏版)》请在冰豆网上搜索。

SQLAlchemy最新权威详细教程.docx

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 其它课程

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1