sqlalchemy - 多个文件 - 关系

1 投票
1 回答
3420 浏览
提问于 2025-04-17 09:43

我有两个类,分别在两个不同的文件里,一个是客户类(customer),另一个是地址类(address)。地址类会在其他地方使用,比如供应商也有地址。客户类需要以三种方式引用地址类。一个客户有一个默认的送货地址(这是一对一的关系),还有一个默认的账单地址(也是一对一的关系),此外,客户还有一个可以选择的多个地址列表,如果不需要默认地址的话。

客户类在ar.py文件里,地址类在global.py文件里。

一对一的关系可以正常工作,但我搞不懂如何让一对多的地址列表在两个不同的文件中正常运作,避免出现循环引用的问题。

谢谢你们提供的任何见解……

globals.py
from erp.model import DeclarativeBase, metadata, DBSession

class Address(DeclarativeBase):
    __tablename__ = 'addresses'
    address_id = Column(Integer,primary_key=True)
    name = Column(Unicode(100))
    address_one = Column(Unicode(100))
    address_two = Column(Unicode(100))
    address_three = Column(Unicode(100))
    city = Column(Unicode(100))
    state = Column(Unicode(100))
    zip_code = Column(Unicode(100))
    phone = Column(Unicode(100))
    fax = Column(Unicode(100))
    contact = Column(Unicode(100))

ar.py ...
from erp.model.globals import Address

class Customer(DeclarativeBase):
    __tablename__ = 'customers'
    customer_id = Column(Integer, primary_key=True)
    customer_name = Column(Unicode(100))
    discount = Column(Float)
    #bill_to_id = Column(Integer, ForeignKey('addresses.address_id'))
    #bill_to = relation(Address,primaryjoin=bill_to_id==Address.address_id,uselist=False)
    ship_to_id = Column(Integer, ForeignKey('addresses.address_id'))
    ship_to = relation(Address,primaryjoin=ship_to_id==Address.address_id,uselist=False)
    locations = relation(Address,backref="customer",primaryjoin='customers.customer_id'=='addresses.customer_id')

如果我把所有东西放在一个文件里,这个问题就能解决,但这样会让项目结构变得复杂,所有内容都挤在一个文件里,或者更糟的是,在ar文件和vendor文件中重复相同的地址类布局。

再次感谢你的帮助!

保罗

1 个回答

1

你可以用字符串来创建模型,而不是用实例。比如说:

ship_to = relation('Address', ...)

SQLAlchemy会帮你把这些字符串转换成对象。

一对多的关系通常是通过地址表中的外键(fkey)指向客户表来处理的。不过,如果你想把地址用于多个目的,这种方法就不太好用了。如果你希望数据库中的所有地址都存储在一个表里,我建议在每个表和地址表之间添加链接表。例如,customer_addresses表会有指向地址表和客户表的外键。另一种选择是为客户地址和供应商地址分别创建不同的表。如果你想这样做,最好的方法是创建一个叫做AddressMixin的东西,这样你就可以把它应用到不同的对象上:

class AddressMixin(object):
    @declared_attr
    def street(cls):
        return Column(Text, ...)

class CustomerAddress(Base, AddressMixin):
    __tablename__ = 'customer_addresses'
    id = ...

撰写回答