码迷,mamicode.com
首页 > 编程语言 > 详细

python之ORM

时间:2018-07-31 15:29:59      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:获取   echo   expr   customer   foreign   could   fir   match   oca   

pymysql

python操作数据库的基本步骤:

  1. 导入相应的python模块;
  2. 使用connect函数连接数据库,并返回一个connection对象;
  3. 通过connection对象的cursor方法,返回一个cursor对象;
  4. 通过cursor对象的execute方法执行SQL语句;
  5. 如果执行的是查询语句,通过cursor对象的fetchall语句获取返回结果;
  6. 调用cursor对象的close方法关闭cursor;
  7. 调用connection对象的close方法关闭数据库连接。
 1 import pymysql
 2 
 3 conn = pymysql.Connect(host=127.0.0.1,user=admin,passwd=admin,db=test_py)
 4 cur = conn.cursor()
 5 
 6 reCount = cur.execute(select * from student)
 7 print(cur.fetchall())    # ((1, ‘gareth‘, 22, datetime.date(2011, 9, 1)),)
 8 
 9 cur.close()
10 conn.close()

 connection类成员

  • begin: 开始事务
  • commit: 提交事务
  • rollback: 回滚事务
  • cursor: 返回一个cursor对象
  • autocommit: 设置是否事务自动提交
  • set_character_set: 设置字符集编码
  • get_server_info: 获取数据库版本信息

注: 一般不直接调用begin,commit和roolback函数,而是通过上下文管理器实现事务的提交与回滚操作。

cursor类成员对象:cursor对象表示数据库游标,用于执行SQL语句并获取SQL语句的执行结果。

  • execute: 执行SQL语句
  • close:关闭游标
  • fetchall:获取SQL语句的所有记录
  • fetchmany:获取SQL语句的多条记录
  • fetchone:获取SQL语句的一条记录
  • owncount:常量,表示SQL语句的结果集中返回了多少条记录
  • arraysize:变量,保存了当前获取纪录的下标
  • lastrowid:获取最新自增ID

注:在fetch数据时按照顺序进行,可以使用cursor.scroll(num,mode)来移动游标位置,如:

  • cursor.scroll(1,mode=‘relative‘)  # 相对当前位置移动
  • cursor.scroll(2,mode=‘absolute‘) # 相对绝对位置移动

默认获取的数据是元祖类型,如果想要或者字典类型的数据,即:

 1 conn = pymysql.Connect(host=127.0.0.1,user=admin,passwd=admin,db=test_py)
 2 cur = conn.cursor(cursor=pymysql.cursors.DictCursor)
 3 
 4 reCount = cur.execute(select * from student)
 5 print(cur.fetchall())
 6 """
 7 [{‘stu_id‘: 1, ‘name‘: ‘gareth‘, ‘age‘: 22, ‘register_data‘: datetime.date(2011, 9, 1)}, 
 8  {‘stu_id‘: 3, ‘name‘: ‘Bob‘, ‘age‘: 19, ‘register_data‘: datetime.date(2012, 2, 3)}, 
 9  {‘stu_id‘: 4, ‘name‘: ‘Bob‘, ‘age‘: 19, ‘register_data‘: datetime.date(2012, 2, 3)}, 
10  {‘stu_id‘: 5, ‘name‘: ‘Mary‘, ‘age‘: 18, ‘register_data‘: datetime.date(2013, 1, 2)}]
11 """
12 
13 cur.close()
14 conn.close()

 使用上下文管理管理数据库:

技术分享图片
 1 import pymysql
 2 import os
 3 
 4 
 5 def get_conn(**kwargs):
 6     if os.getenv(DB,MYSQL) == MYSQL:
 7         return pymysql.connect(host=kwargs.get(host,localhost),
 8                                user=kwargs.get(user),
 9                                passwd=kwargs.get(passwd),
10                                port=kwargs.get(port,3306),
11                                db=kwargs.get(db))
12 
13 def execute_sql(conn, sql):
14     with conn as cur:
15         cur.execute(sql)
16 
17 def insert_data(conn,sname,sage,sregister):
18     INSERT_FORMAT = """insert into student (name,age,register_data) values(‘{0}‘,‘{1}‘,‘{2}‘)"""
19     sql = INSERT_FORMAT.format(sname,sage,sregister)
20     execute_sql(conn,sql)
21 
22 def main():
23     conn = get_conn(host=127.0.0.1,
24                     user=admin,
25                     passwd=admin,
26                     port=3306,
27                     db=test_py)
28 
29     try:
30         insert_data(conn,Bob,19,2012-02-03)
31         insert_data(conn,Mary,18,2013-01-02)
32 
33         with conn as cur:
34             cur.execute(select * from student)
35             rows = cur.fetchall()
36             for row in rows:
37                 print(row)
38     finally:
39         if conn:
40             conn.close()
41 
42 if __name__ == __main__:
43     main()
View Code

 上面例子中如果values(‘{0}‘,‘{1}‘,‘{2}‘)的引号去掉,则会报错:pymysql.err.InternalError: (1054, "Unknown column ‘jack‘ in ‘field list‘")

1 cur.execute("insert into student (name,age,register_data) values(‘jack‘,12,‘2012-02-03‘)")
2 
3 INSERT_FORMAT = """insert into student (name,age,register_data) values(‘{0}‘,‘{1}‘,‘{2}‘)"""

 批量插入:

1 cur = conn.cursor()
2 
3 cur.executemany("insert into student (name,age,register_data) values(%s,%s,%s)",
4             [(jack,12,2012-02-03),(Bob,12,2012-02-03)]  )

ORM

orm英文全称object relational mapping,即对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了保证一致的使用习惯,通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sql语言。

优点:
  •  隐藏了数据访问细节,“封闭”的通用数据库交互,ORM的核心。他使得我们的通用数据库交互变得简单易行,并且完全不用考虑该死的SQL语句。快速开发,由此而来。
  • ORM使我们构造固化数据结构变得简单易行。
缺点:
  •  自动化意味着映射和关联管理,代价是牺牲性能

sqlalchemy

SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取执行结果。

 技术分享图片

SQLAlchemy本身无法操作数据库,其必须依赖pymsql等第三方插件,Dialect用于和数据API进行交流,根据配置文件的不同调用不同的数据库API,从而实现对数据库的操作,如:

技术分享图片
 1 MySQL-Python
 2     mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
 3    
 4 pymysql
 5     mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
 6    
 7 MySQL-Connector
 8     mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>
 9    
10 cx_Oracle
11     oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]
12    
13 更多详见:http://docs.sqlalchemy.org/en/latest/dialects/index.html
dialect

使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。

 1 from sqlalchemy import create_engine
 2 
 3 engine = create_engine(mysql+pymysql://user_account:password@127.0.0.1/test, max_overflow=5)
 4 
 5 cur = engine.execute("insert into student(name,age,register_date) values(‘Jack‘,20,‘2018-01-02‘)")
 6 print(cur.lastrowid)
 7 # 1
 8 
 9 cur = engine.execute("insert into student(name,age,register_date) values(%s,%s,%s)",
10                      [(Gareth,18,2018-07-02),(Mar,17,2017-12-02)])
11 
12 cur = engine.execute("insert into student(name,age,register_date) values(%(name)s,%(age)s,%(register_date)s)",
13                      name = Ker,age = 21,register_date=2016-09-01)
14 cur = engine.execute(select * from student)
15 print(cur.fetchone())
16 # (1, ‘Jack‘, 20, datetime.date(2018, 1, 2))
17 print(cur.fetchmany(2))
18 # [(2, ‘Gareth‘, 18, datetime.date(2018, 7, 2)), (3, ‘Mar‘, 17, datetime.date(2017, 12, 2))]
19 print(cur.fetchall())
20 # [(4, ‘Ker‘, 21, datetime.date(2016, 9, 1))]

ORM使用

使用 Engine/ConnectionPooling/Dialect 进行数据库操作,Engine使用ConnectionPooling连接数据库,然后再通过Dialect执行SQL语句。

创建表:

 1 from sqlalchemy.ext.declarative import declarative_base
 2 from sqlalchemy import Column,Integer,String,ForeignKey, UniqueConstraint,Index
 3 from sqlalchemy.orm import sessionmaker, relationship
 4 from sqlalchemy import create_engine
 5 
 6 
 7 engine = create_engine("mysql+pymysql://user_account:password@127.0.0.1:3306/test", max_overflow = 5)
 8 Base = declarative_base()  # 生成一个基类
 9 
10 class Classes(Base):
11     __tablename__=classes
12     id = Column(Integer, primary_key=True)
13     name = Column(String(32))
14 
15 Base.metadata.create_all(engine) #创建表结构

创建与数据库的会话session:

1 session_class = sessionmaker(bind=engine)  # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
2 session = session_class()                  # 生成session实例
3 
4 cla_obj = Classes(name=python099)  #生成你要创建的数据对象
5 
6 session.add(cla_obj)  # 把要创建的数据对象添加到这个session里, 一会统一创建
7 
8 session.commit()      # 现此才统一提交,创建数据
查询

sqlalchemy把返回的数据映射成一个对象,调用每个字段可以像调用对象属性一样。

 1 session_class = sessionmaker(bind=engine)  # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
 2 session = session_class()                  # 生成session实例
 3 
 4 
 5 my_classes = session.query(Classes)
 6 print(my_classes)
 7 #  "SELECT classes.id AS classes_id, classes.name AS classes_name FROM classes"
 8 
 9 my_classes = session.query(Classes).first()
10 print(my_classes)                                  # 返回内存对象地址
11     # <__main__.Classes object at 0x000001832CE1A4E0>
12 
13 my_classes = session.query(Classes).first()
14 print(id: ,my_classes.id,name:,my_classes.name)
15     # id:  1 name: python011
16 
17 my_classes = session.query(Classes)
18 for classes in my_classes:
19     # print(‘id: ‘,classes.id,‘name:‘,classes.name)
20     # id: 1   name: python011
21     # id: 2   name: python016
22     # id: 3   name: linux

把内存对象地址转化为可读性数据,除了调用字段还可以使用__repr__(self) 函数。

 1 def __repr__(self):
 2     return "Classes(id=%s,name=%s)"%(self.id, self.name)
 3 
 4 my_classes = session.query(Classes)
 5 print(my_classes)     # SELECT classes.id AS classes_id, classes.name AS classes_name FROM classes
 6 
 7 print(my_classes[1])  # Classes(id=2,name=python016)
 8 
 9 for classes in my_classes:
10     print(classes)
11 # Classes(id=1,name=python011)
12 # Classes(id=2,name=python016)
13 # Classes(id=3,name=linux)

过滤

1 print(session.query(Classes).filter(Classes.name.in_([mysql,python_sqlalchemy])).all())
2 
3 session.query(Classes).filter_by(name=python011).first()

多条件查询: 相当于id > 1 and id <4

1 obj = session.query(Classes).filter(Classes.id>1).filter(Classes.id<4).all()
2 print(obj)  
3 # [Classes(id=2,name=python016), Classes(id=3,name=linux)]

获取所有数据

1 print(session.query(Classes).all())
2 # [Classes(id=1,name=python_mysql), Classes(id=2,name=python016), Classes(id=3,name=linux)]
3 print(session.query(Classes.id,Classes.name).all())
4 #  [(1, ‘python_mysql‘), (2, ‘python016‘), (3, ‘linux‘)]

查询语法

技术分享图片
 1 Common Filter Operators
 2 
 3 Here’s a rundown of some of the most common operators used in filter():
 4 
 5 equals:
 6 
 7      query.filter(User.name == ed)
 8 not equals:
 9 
10      query.filter(User.name != ed)
11 LIKE:
12 
13 query.filter(User.name.like(%ed%))
14 
15 IN:
16 
17 NOT IN:
18 query.filter(~User.name.in_([ed, wendy, jack]))
19 
20 IS NULL:
21 
22 IS NOT NULL:
23 
24 AND:
25 2.1. ObjectRelationalTutorial 17
26 
27 query.filter(User.name.in_([ed, wendy, jack]))
28 # works with query objects too:
29 query.filter(User.name.in_( session.query(User.name).filter(User.name.like(%ed%))
30 
31 ))
32 
33 query.filter(User.name == None)
34 # alternatively, if pep8/linters are a concern
35 query.filter(User.name.is_(None))
36 query.filter(User.name != None)
37 # alternatively, if pep8/linters are a concern
38 query.filter(User.name.isnot(None))
39 SQLAlchemy Documentation, Release 1.1.0b1
40 
41 # use and_()
42 
43 from sqlalchemy import and_
44 query.filter(and_(User.name == ed, User.fullname == Ed Jones))
45 
46 # or send multiple expressions to .filter()
47 query.filter(User.name == ed, User.fullname == Ed Jones)
48 # or chain multiple filter()/filter_by() calls
49 query.filter(User.name == ed).filter(User.fullname == Ed Jones)
50 Note: Makesureyouuseand_()andnotthePythonandoperator! ? OR:
51 
52 Note: Makesureyouuseor_()andnotthePythonoroperator! ? MATCH:
53 
54 query.filter(User.name.match(wendy))
55 Note: match() uses a database-specific MATCH or CONTAINS f 
View Code
分组和统计
 1 print(session.query(Classes).filter(Classes.name.like(p%)).count())
 2 # 2
 3 print(session.query(Classes).count())
 4 # 2
 5 
 6 from sqlalchemy import func
 7 print(session.query(Classes).all())
 8 # [Classes(id=1,name=python_mysql), Classes(id=2,name=python016), Classes(id=3,name=linux), Classes(id=5,name=linux)]
 9 
10 print(session.query(func.count(Classes.name),Classes.name).group_by(Classes.name).all())
11 #[(1, ‘python_mysql‘), (1, ‘python016‘), (2, ‘linux‘)]
修改

使用修改,可以加个判断,如果没有查询到需要修改的信息则跳过,否则容易出现异常  AttributeError 

 1 my_classes = session.query(Classes).filter_by(name=python011).first()
 2 
 3 my_classes.name = python_mysql022
 4 session.commit()
 5 my_classes = session.query(Classes)
 6 for classes in my_classes:
 7     print(classes)
 8 
 9 # Classes(id=1,name=python_mysql)
10 # Classes(id=2,name=python016)
11 # Classes(id=3,name=linux)

异常:

1 Traceback (most recent call last):
2   File "C:/D/personal_data/workspace/eleven/mysql_study/class_study/orm_01.py", line 64, in <module>
3     my_classes.name = python_mysql022
4 AttributeError: NoneType object has no attribute name
回滚
 1 my_classes = session.query(Classes).filter_by(id=2).first()
 2 my_classes.name = python_sqlalchemy
 3 
 4 fake_classes = Classes(name=mysql)
 5 session.add(fake_classes)
 6 
 7 print(session.query(Classes).filter(Classes.name.in_([mysql,python_sqlalchemy])).all())
 8 #[Classes(id=2,name=python_sqlalchemy), Classes(id=4,name=mysql)]
 9 session.rollback()
10 
11 print(session.query(Classes).filter(Classes.name.in_([mysql,python_sqlalchemy])).all())
12 # []

程序:

技术分享图片
  1 from sqlalchemy.ext.declarative import declarative_base
  2 from sqlalchemy import Column,Integer,String,ForeignKey, UniqueConstraint,Index
  3 from sqlalchemy.orm import sessionmaker, relationship
  4 from sqlalchemy import create_engine
  5 
  6 
  7 engine = create_engine("mysql+pymysql://jiawenyx:intel@3117@127.0.0.1:3306/test", max_overflow = 5)
  8 Base = declarative_base()
  9 
 10 class Classes(Base):
 11     __tablename__=classes
 12     id = Column(Integer, primary_key=True)
 13     name = Column(String(32))
 14 
 15     def __repr__(self):
 16         return "Classes(id=%s,name=%s)"%(self.id, self.name)
 17 
 18 Base.metadata.create_all(engine) #创建表结构
 19 
 20 session_class = sessionmaker(bind=engine)  # 创建与数据库的会话session class ,注意,这里返回给session的是个class,不是实例
 21 session = session_class()                  # 生成session实例
 22 #
 23 # cla_obj = Classes(name=‘python016‘)  #生成你要创建的数据对象
 24 # cla_obj2 = Classes(name=‘linux‘)
 25 #
 26 # session.add(cla_obj)  # 把要创建的数据对象添加到这个session里, 一会统一创建
 27 # session.add(cla_obj2)
 28 # session.commit()      # 现此才统一提交,创建数据
 29 
 30 
 31 # ********************************   查询  ***************************************
 32 
 33 my_classes = session.query(Classes)
 34 # print(my_classes)
 35 #  "SELECT classes.id AS classes_id, classes.name AS classes_name FROM classes"
 36 my_classes = session.query(Classes).first()
 37 # print(my_classes)
 38 # <__main__.Classes object at 0x000001832CE1A4E0>
 39 my_classes = session.query(Classes).first()
 40 # print(‘id: ‘,my_classes.id,‘name:‘,my_classes.name)
 41 # id:  1 name: python011
 42 
 43 my_classes = session.query(Classes)
 44 # for classes in my_classes:
 45     # print(‘id: ‘,classes.id,‘name:‘,classes.name)
 46     # id: 1   name: python011
 47     # id: 2   name: python016
 48     # id: 3   name: linux
 49 
 50 
 51 # my_classes = session.query(Classes)
 52 # print(my_classes)     # SELECT classes.id AS classes_id, classes.name AS classes_name FROM classes
 53 # print(my_classes[1])  # Classes(id=2,name=python016)
 54 # for classes in my_classes:
 55 #     print(classes)
 56 # # Classes(id=1,name=python011)
 57 # # Classes(id=2,name=python016)
 58 # # Classes(id=3,name=linux)
 59 
 60 #******************************************  修改  ********************************************
 61 
 62 my_classes = session.query(Classes).filter_by(name=python011).first()
 63 
 64 # my_classes.name = ‘python_mysql022‘
 65 # session.commit()
 66 # my_classes = session.query(Classes)
 67 # for classes in my_classes:
 68 #     print(classes)
 69 
 70 # Classes(id=1,name=python_mysql)
 71 # Classes(id=2,name=python016)
 72 # Classes(id=3,name=linux)
 73 
 74 # *******************************  回滚  ********************************
 75 
 76 my_classes = session.query(Classes).filter_by(id=2).first()
 77 my_classes.name = python_sqlalchemy
 78 
 79 fake_classes = Classes(name=mysql)
 80 session.add(fake_classes)
 81 
 82 # print(session.query(Classes).filter(Classes.name.in_([‘mysql‘,‘python_sqlalchemy‘])).all())
 83 #[Classes(id=2,name=python_sqlalchemy), Classes(id=4,name=mysql)]
 84 session.rollback()
 85 
 86 # print(session.query(Classes).filter(Classes.name.in_([‘mysql‘,‘python_sqlalchemy‘])).all())
 87 
 88 
 89 # **********************获取所有数据*****************************
 90 
 91 # print(session.query(Classes).all())
 92 # # [Classes(id=1,name=python_mysql), Classes(id=2,name=python016), Classes(id=3,name=linux)]
 93 # print(session.query(Classes.id,Classes.name).all())
 94 # #  [(1, ‘python_mysql‘), (2, ‘python016‘), (3, ‘linux‘)]
 95 #
 96 # # ********************** 多条件查询 ****************************
 97 #
 98 # obj = session.query(Classes).filter(Classes.id>1).filter(Classes.id<4).all()
 99 # print(obj)
100 # # [Classes(id=2,name=python016), Classes(id=3,name=linux)]
101 #
102 # # ********************** 统计和分组 ****************************
103 #
104 print(session.query(Classes).filter(Classes.name.like(p%)).count())
105 # 2
106 print(session.query(Classes).count())
107 # 2
108 
109 from sqlalchemy import func
110 print(session.query(Classes).all())
111 # [Classes(id=1,name=python_mysql), Classes(id=2,name=python016), Classes(id=3,name=linux), Classes(id=5,name=linux)]
112 print(session.query(func.count(Classes.name),Classes.name).group_by(Classes.name).all())
113 #[(1, ‘python_mysql‘), (1, ‘python016‘), (2, ‘linux‘)]
程序

外键

技术分享图片
 1 from sqlalchemy import Column,Integer,String
 2 from sqlalchemy import ForeignKey
 3 from sqlalchemy.orm import relationship
 4 from sqlalchemy.ext.declarative import declarative_base
 5 from sqlalchemy import create_engine
 6 from sqlalchemy.orm import sessionmaker
 7 
 8 engine = create_engine("mysql+pymysql://user:password@127.0.0.1:3306/test", max_overflow = 5)
 9 
10 Base = declarative_base()
11 
12 class Customer(Base):
13     __tablename__=customer
14     id = Column(Integer,primary_key=True)
15     name = Column(String(32))
16     billing_address_id = Column(Integer,ForeignKey(address.id))
17     shipping_address_id = Column(Integer)
18     #shipping_address_id = Column(Integer,ForeignKey(‘address.id‘))
19     address = relationship(Address, backref=customer)
20   #  shipping_address = relationship(‘Address‘)
21     def __repr__(self):
22         return "id:%s,name:%s,billing_address_id:%s,shipping_address_id:%s"23                %(self.id,self.name,self.billing_address_id,self.shipping_address_id)
24 
25 class Address(Base):
26     __tablename__ = address
27     id = Column(Integer,primary_key=True)
28     stress = Column(String(64))
29     city = Column(String(64))
30     state = Column(String(64))
31 
32     def __repr__(self):
33         return id:%s,stress:%s,city:%s,state:%s %(self.id,self.stress,self.city,self.state)
34 
35 Base.metadata.create_all(engine) #创建表结构
36 
37 session_class = sessionmaker(engine)
38 session = session_class()
39 
40 # cus1 = Customer(name=‘gareth‘,billing_address_id=1, shipping_address_id = 2)
41 # cus2 = Customer(name = ‘Jack‘,billing_address_id=2, shipping_address_id = 3)
42 # cus3 = Customer(name =‘Mar‘,billing_address_id=3, shipping_address_id = 3)
43 #
44 # add_obj = Address(stress = ‘shuangxing‘, city = ‘shunyi‘, state= ‘Beijing‘)
45 # add_obj1 = Address(stress = ‘tiantongyuan‘, city = ‘changping‘, state = ‘Beijing‘)
46 # add_obj2 = Address(stress = ‘bayiqiao‘, city = ‘nanchang‘, state = ‘jiangxi‘)
47 # session.add_all([add_obj,add_obj1,add_obj2,cus1,cus2,cus3])
48 #
49 # session.commit()
50 
51 obj = session.query(Address).first()
52 # print(obj)      # id:1,stress:shuangxing,city:shunyi,state:Beijing
53 # print(obj.customer)  # [id:1,name:gareth,billing_address_id:1,shipping_address_id:2]
54 # for i in obj.customer:
55 #     print(i)  # id:1,name:gareth,billing_address_id:1,shipping_address_id:2
56 
57 obj = session.query(Customer).first()
58 # print(obj)    # id:1,name:gareth,billing_address_id:1,shipping_address_id:2
59 # print(obj.address)  # id:1,stress:shuangxing,city:shunyi,state:Beijing
外键

注:

定义外键:  billing_address_id = Column(Integer,ForeignKey(‘address.id‘))

relationship:address = relationship(‘Address‘, backref=‘customer‘),通过Address表可以反查customer信息,可以在Customer表中通过address字段,查找Adress表中信息;从而两张表互查。

1 obj = session.query(Customer).first()
2 print(obj)          # id:1,name:gareth,billing_address_id:1,shipping_address_id:2
3 print(obj.address)  # id:1,stress:shuangxing,city:shunyi,state:Beijing
1 obj = session.query(Address).first()
2 print(obj)      # id:1,stress:shuangxing,city:shunyi,state:Beijing
3 print(obj.customer)  # [id:1,name:gareth,billing_address_id:1,shipping_address_id:2]
4 for i in obj.customer:
5     print(i)  # id:1,name:gareth,billing_address_id:1,shipping_address_id:2

多外键关联

 1 from sqlalchemy import Column,Integer,String
 2 from sqlalchemy import ForeignKey
 3 from sqlalchemy.orm import relationship
 4 from sqlalchemy.ext.declarative import declarative_base
 5 from sqlalchemy import create_engine
 6 from sqlalchemy.orm import sessionmaker
 7 
 8 engine = create_engine("mysql+pymysql://user:password@127.0.0.1:3306/test", max_overflow = 5)
 9 
10 Base = declarative_base()
11 
12 class Customer(Base):
13     __tablename__=customer
14     id = Column(Integer,primary_key=True)
15     name = Column(String(32))
16     billing_address_id = Column(Integer,ForeignKey(address.id))
17     shipping_address_id = Column(Integer,ForeignKey(address.id))
18     address = relationship(Address)
19     shipping_address = relationship(Address)
20     def __repr__(self):
21         return "id:%s,name:%s,billing_address_id:%s,shipping_address_id:%s"22                %(self.id,self.name,self.billing_address_id,self.shipping_address_id)
23 
24 class Address(Base):
25     __tablename__ = address
26     id = Column(Integer,primary_key=True)
27     stress = Column(String(64))
28     city = Column(String(64))
29     state = Column(String(64))
30 
31     def __repr__(self):
32         return id:%s,stress:%s,city:%s,state:%s %(self.id,self.stress,self.city,self.state)
33 
34 Base.metadata.create_all(engine) #创建表结构
35 
36 session_class = sessionmaker(engine)
37 session = session_class()

创建表结构OK,但Address表中插入数据时会报下面的错

sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship Customer.address - 
there are multiple foreign key paths linking the tables.  Specify the foreign_keys argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table. 

修改方法:

1 class Customer(Base):
2     __tablename__=customer
3     id = Column(Integer,primary_key=True)
4     name = Column(String(32))
5     billing_address_id = Column(Integer,ForeignKey(address.id))
6     shipping_address_id = Column(Integer,ForeignKey(address.id))
7     billing_address = relationship(Address,foreign_keys=[billing_address_id])
8     shipping_address = relationship(Address,foreign_keys=[shipping_address_id])

处理中文

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

1 eng = create_engine(mysql://root:root@localhost:3306/test2?charset=utf8,echo=True)

 

python之ORM

标签:获取   echo   expr   customer   foreign   could   fir   match   oca   

原文地址:https://www.cnblogs.com/gareth-yu/p/9363147.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!