sqlalchemy多外键关联
一、前言
如果有张表A的多个字段关联另一张表B的一个字段,就如同一个客户表的账单地址和发货地址,同时关联地址表中的id字段。
二、事例
# -*- coding: UTF-8 -*- from sqlalchemy import create_engine from sqlalchemy import Integer, ForeignKey, String, Column from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import relationship engine = create_engine("mysql+pymysql://bigberg:111111@172.16.200.49:3306/study", encoding="utf-8", ) # 连接数据库,echo=True =>把所有的信息都打印出来 Base = declarative_base() # 生成orm基类 class Customer(Base): __tablename__ = 'customer' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) # 多个外键关联 billing_address_id = Column(Integer, ForeignKey("address.id")) shopping_address_id = Column(Integer, ForeignKey("address.id")) # foreign_keys 一定要加,否则会报错 billing_address = relationship("Address",foreign_keys=[billing_address_id]) shopping_address = relationship("Address",foreign_keys=[shopping_address_id]) class Address(Base): __tablename__ = 'address' id = Column(Integer, primary_key=True) street = Column(String(64), nullable=False) city = Column(String(64), nullable=False) state = Column(String(64), nullable=False) def __repr__(self): return "省份:%s 城市:%s 街区:%s" %(self.state, self.city, self.street) # 创建表 Base.metadata.create_all(engine)
插入数据,为了整体的简洁,数据操作在另一张表进行
1 # -*- coding: UTF-8 -*- 2 import multi_fk 3 from multi_fk import Customer 4 from multi_fk import Address 5 from sqlalchemy.orm import sessionmaker 6 7 # 创建session会话 8 Session_class = sessionmaker(bind=multi_fk.engine) 9 # 生成session实例 10 session = Session_class() 11 12 # 数据 13 address_obj1 = Address(street='daguanlu', city='hz', state='zj') 14 address_obj2 = Address(street='gudunlu', city='hz', state='zj') 15 address_obj3 = Address(street='xinjiekou', city='nj', state='js') 16 session.add_all([address_obj1,address_obj2,address_obj3]) 17 18 customer_obj1 = Customer(name="bigberg", billing_address=address_obj1, 19 shopping_address=address_obj2) 20 21 customer_obj2 = Customer(name="Jack", billing_address=address_obj3, 22 shopping_address=address_obj3) 23 24 session.add_all([customer_obj1,customer_obj2]) 25 26 session.commit()
数据和表结构
mysql> select * from address; +----+-----------+------+-------+ | id | street | city | state | +----+-----------+------+-------+ | 1 | daguanlu | hz | zj | | 2 | gudunlu | hz | zj | | 3 | xinjiekou | nj | js | +----+-----------+------+-------+ 3 rows in set (0.00 sec) mysql> select * from customer; +----+---------+--------------------+---------------------+ | id | name | billing_address_id | shopping_address_id | +----+---------+--------------------+---------------------+ | 1 | bigberg | 1 | 2 | | 2 | Jack | 3 | 3 | +----+---------+--------------------+---------------------+ 2 rows in set (0.00 sec) mysql> desc address; +--------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | street | varchar(64) | NO | | NULL | | | city | varchar(64) | NO | | NULL | | | state | varchar(64) | NO | | NULL | | +--------+-------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec) mysql> desc customer; +---------------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(32) | NO | | NULL | | | billing_address_id | int(11) | YES | MUL | NULL | | | shopping_address_id | int(11) | YES | MUL | NULL | | +---------------------+-------------+------+-----+---------+----------------+ 4 rows in set (0.00 sec)
查询
# -*- coding: UTF-8 -*- import multi_fk from multi_fk import Customer from multi_fk import Address from sqlalchemy.orm import sessionmaker # 创建session会话 Session_class = sessionmaker(bind=multi_fk.engine) # 生成session实例 session = Session_class() obj = session.query(Customer).filter(Customer.name=='bigberg').first() print(obj.name,'\n','bill_address:',obj.billing_address,'\n', 'shopping_address:', obj.shopping_address) session.commit() #输出 bigberg bill_address: 省份:zj 城市:hz 街区:daguanlu shopping_address: 省份:zj 城市:hz 街区:gudunlu