python orm_python-ORM

ORM 对象映射关系程序。

通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。

orm的优点:

隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。

ORM使我们构造固化数据结构变得简单易行。

缺点:

无可避免的,自动化意味着映射和关联管理,代价是牺牲性能(早期,这是所有不喜欢ORM人的共同点)。现在的各种ORM框架都在尝试使用各种方法来减轻这块(LazyLoad,Cache),效果还是很显著的。

最有名的ORM框架是SQLAlchemy,系统中没有该模块的需要安装 pip install sqlalchemy (或easy_install SQLAlchemy)

如果在pip install sqlalchemy 中报ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org'错,需要先设置超时时间:pip --default-timeout=100 install -U Pillow,再重新安装 pip install sqlalchemy,通过imort sqlalchemy验证是否安装正常。

ORM框架SQLAlchemy 使用,创建表:

#conding:utf-8

import sqlalchemy

from sqlalchemy import create_engine

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy import Column,Integer,String #区分大小写

#创建连接

engine=create_engine("mysql+pymysql://root:123456@localhost/ceshi",encoding='utf-8',echo=True)

#生成orm基类

base=declarative_base()

class user(base):

__tablename__ = 'users' #表名

id = Column(Integer, primary_key=True)

name = Column(String(32))

password = Column(String(64))

base.metadata.create_all(engine) #创建表结构

注:pymysql设置编码字符集一定要在数据库访问的URL上增加?charset=utf8,否则数据库的连接就不是utf8的编码格式

engine=create_engine("mysql+pymysql://root:123456@localhost/ceshi",encoding='utf-8',echo=True)

ORM框架SQLAlchemy 使用,插入数据:

#conding:utf-8

import sqlalchemy

from sqlalchemy import create_engine

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy import Column,Integer,String #区分大小写

from sqlalchemy.orm import sessionmaker

#创建连接

engine=create_engine("mysql+pymysql://root:123456@localhost/ceshi",encoding='utf-8',echo=True)

#生成orm基类

base=declarative_base()

class user(base):

__tablename__ = 'users' #表名

id = Column(Integer, primary_key=True)

name = Column(String(32))

password = Column(String(64))

base.metadata.create_all(engine) #创建表结构

Session_class=sessionmaker(bind=engine) ##创建与数据库的会话,class,不是实例

Session=Session_class() #生成session实例

user_obj = user(name="rr",password="123456") #插入你要创建的数据对象,每执行一次都会新增一次数据。

print user_obj.name,user_obj.id #此时还没创建对象呢,不信你打印一下id发现还是None

Session.add(user_obj) #把要创建的数据对象添加到这个session里

print user_obj.name,user_obj.id #此时也依然还没创建

Session.commit() #提交,使前面修改的数据生效。

结果:

1386244-20180821170820675-494137570.png

查询:

my_user = Session.query(user).filter_by(name="ee").first() #创建查询对象

print(my_user.id,my_user.name,my_user.password) #输出查询内容

print my_user #内存地址

结果:

1386244-20180822182211676-472657176.png

修改:

my_user = Session.query(user).filter_by(name="yy").first() #根据指定条件创建符合条件的对象

my_user.name='uu' #将name='yy'的name修改为uu

print(my_user.id,my_user.name,my_user.password) #输出查询内容

结果:

1386244-20180822183515243-230531404.png

参考数据表:

1386244-20180822193519173-1377328964.png

回滚:

user_obj = user(name="kk",password="99999") #插入你要创建的数据对象

Session.add(user_obj) #把要创建的数据对象添加到这个session里

my_user = Session.query(user).filter_by(name="rr").first() #根据指定条件创建符合条件的对象,first()是指name='rr'的第一条记录

my_user.name="gg" #将name='yy'的name修改为uu

print(Session.query(user).filter(user.name.in_(["gg","kk"])).all()) #显示修改后的数据

Session.rollback() #回滚

print(Session.query(user).filter(user.name.in_(["gg","kk"])).all()) #显示回滚后的内容

结果:

1386244-20180822185824903-1342605950.png

获取所有数据

print Session.query(user.id,user.name).all() #只显示id,name

结果:

1386244-20180822191444105-1063336330.png

多条件查询

objs = Session.query(user).filter(user.id>0).filter(user.id<=3).all() #注意:filter()中的关键字不能是表达式user.id=0

print objs

filter的关系相当于 user.id >0 AND user.id <=3 的效果

结果:

1386244-20180822193420671-914836345.png

统计和分组

objs = Session.query(user).filter(user.name.like('r%')).count() #统计

print objs

结果:

1386244-20180822194114132-1148145283.png

from sqlalchemy import func

print(Session.query(func.count(user.name),user.name).group_by(user.name).all() ) #分组

结果:

1386244-20180822194437133-1382190049.png

外键关联

参照表:两张表是一对多的关系。

users(一)

1386244-20180823101006126-1418943325.png

addresses(多)

1386244-20180823100942466-1684271929.png

创建表addresses,将users表中的id作为addresses表的外键。

import sqlalchemy

from sqlalchemy import create_engine

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy import Column,Integer,String,ForeignKey #区分大小写

from sqlalchemy.orm import sessionmaker,relationship

#创建连接

engine=create_engine("mysql+pymysql://root:123456@localhost/ceshi",encoding='utf-8',echo=True)

#生成orm基类

base=declarative_base()

class user(base):

__tablename__ = 'users' #表名

id = Column(Integer, primary_key=True)

name = Column(String(32))

password = Column(String(64))

def __repr__(self):

return "" % (self.id,

self.name, self.password)

class Address(base):

__tablename__ = 'addresses'

id = Column(Integer, primary_key=True)

email_address = Column(String(32), nullable=False)

user_id = Column(Integer, ForeignKey('users.id'))

user = relationship("user", backref="addresses")

'''允许你在user表里通过backref字段反向查出所有它在addresses表里的关联项,在内存中创建。在addresses表中可以使用user来查询users表中的数据,在users表中可以使用backref后的addresses来查询assresses表中的数据。'''

def __repr__(self):

return "

" % (self.email_address,self.id,self.user_id)

base.metadata.create_all(engine) #创建表结构

Session_class=sessionmaker(bind=engine) #创建与数据库的会话,class,不是实例

Session=Session_class() #生成session实例

obj = Session.query(user).first()

print obj.addresses #在users表里面通过addresses来查询addresses表中的数据。

for i in obj.addresses:

print i

addr_obj = Session.query(Address).first()

print(addr_obj.user) #在addresses表中通过user来查询users表中的数据。

print(addr_obj.user.name)

Session.commit() #提交,使前面修改的数据生效。

结果:

1386244-20180823102114750-701192549.png

输出的结果1是列表形式,print 多行记录时以列表的形式显示。

注:在定义表的类下面加 def __repr__(self):return ... 是为了在print时输出哪些数据,以及输出后的显示形式。

补充:1.主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性

2.外键:是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的。所以说,如果谈到了外键,一定是至少涉及到两张表。例如下面这两张表:

1386244-20180823094952503-873785191.jpg

设定条件向指定表中添加记录:

obj = Session.query(user).filter(user.name=='ee').all()[0] #设定条件

print(obj.addresses)

obj.addresses = [Address(email_address="ertttt"), #向addresses表中添加2列。

Address(email_address="dddd")]

结果:

1386244-20180823104037130-690510587.png

1386244-20180823104054940-1334799667.png

多外键关联

在Customer表有2个字段都关联了Address表

class Customer(base):

__tablename__ = 'customer'

id = Column(Integer, primary_key=True)

name = Column(String)

billing_address_id = Column(Integer, ForeignKey("address.id"))

shipping_address_id = Column(Integer, ForeignKey("address.id"))

'''#创建的列billing_address_id、shipping_address_id都作为外键关联address表中id列'''

billing_address = relationship("Address")

shipping_address = relationship("Address")#创建两个关联项

class Address(base):

__tablename__ = 'address'

id = Column(Integer, primary_key=True)

street = Column(String)

city = Column(String)

state = Column(String)

如果报错:

sqlalchemy.exc.AmbiguousForeignKeysError: Couldnot determine join

condition between parent/child tables on relationship

Customer.billing_address- there are multiple foreign key

需要在

illing_address = relationship("Address", foreign_keys=[billing_address_id])

shipping_address = relationship("Address", foreign_keys=[shipping_address_id])

使pymysql分清哪个外键是对应哪个字段。

多对多关系

from sqlalchemy import Table, Column, Integer,String,DATE, ForeignKey

from sqlalchemy.orm import relationship

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy import create_engine

from sqlalchemy.orm import sessionmaker

engine=create_engine("mysql+pymysql://root:123456@localhost/ceshi",encoding='utf-8',echo=True)

base = declarative_base()

book_m2m_author = Table('book_m2m_author', base.metadata,

Column('book_id',Integer,ForeignKey('books.id')),

Column('author_id',Integer,ForeignKey('authors.id')),

) #创建book_m2m_author表,关联另外两张表。

class Book(base):

__tablename__ = 'books'

id = Column(Integer,primary_key=True)

name = Column(String(64))

pub_date = Column(DATE)

authors = relationship('Author',secondary=book_m2m_author,backref='books')

def __repr__(self):

return self.name

class Author(base):

__tablename__ = 'authors'

id = Column(Integer, primary_key=True)

name = Column(String(32))

def __repr__(self):

return self.name

base.metadata.create_all(engine) #创建表结构

Session_class=sessionmaker(bind=engine) #创建与数据库的会话,class,不是实例

Session=Session_class()

b1 = Book(name="跟A学Python")

b2 = Book(name="跟A学linux")

b3 = Book(name="跟A学java")

b4 = Book(name="跟C学开发")

a1 = Author(name="A")

a2 = Author(name="B")

a3 = Author(name="C")

b1.authors = [a1,a2] #建立关系

b2.authors = [a1,a2,a3]

Session.add_all([b1,b2,b3,b4,a1,a2,a3])

Session.commit()

结果:

1386244-20180823123510671-626029538.png

1386244-20180823123530920-1809465321.png

1386244-20180823123435669-894709044.png

用orm查一下数据

book_obj = Session.query(Book).filter_by(name="跟A学Python").first()

print(book_obj.name, book_obj.authors)#这里book_obj.authors只输出name,因为定义类Author时在__repr__(self):定义了返回值

author_obj =Session.query(Author).filter_by(name="A").first()

print(author_obj.name , author_obj.books)

结果:

1386244-20180823125100612-1116929873.png

1386244-20180823125133536-1275581016.png

多对多删除

1.通过书删除作者,删除的是关系。

author_obj =Session.query(Author).filter_by(name="C").first()

book_obj = Session.query(Book).filter_by(name="跟A学linux").first()

book_obj.authors.remove(author_obj) #通过指定书里删除作者,删除的是关系,作者不受影响。

2.删除作者的同时也删除关系。

author_obj =Session.query(Author).filter_by(name="A").first()

Session.delete(author_obj) #delete删除作者A,关系也会删除掉。

结果:

books表

1386244-20180823130909364-1374275154.png

authors表

1386244-20180823130924400-1214801773.png

book_m2m_author表

1386244-20180823130935980-458988109.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值