使用外键映射使用Python和SQLAlchemy从另一个表中获取数据

时间:2010-05-27 04:25:52

标签: python sqlalchemy

嗯,标题比我想象的更难制定。

基本上,我使用SQLAlchemy将这些简单的类映射到表。我知道他们缺少一些项目,但这些并不是突出问题所必需的。

class Customer(object):
    def __init__(self, uid, name, email):
        self.uid = uid
        self.name = name
        self.email = email

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "Cust: %s, Name: %s (Email: %s)" %(self.uid, self.name, self.email)  

以上基本上是一个具有身份证,姓名和电子邮件地址的简单客户。

class Order(object):
    def __init__(self, item_id, item_name, customer):
        self.item_id = item_id
        self.item_name = item_name
        self.customer = None

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "Item ID %s: %s, has been ordered by customer no. %s" %(self.item_id, self.item_name, self.customer)  

这是仅保存订单信息的Orders类:id,名称和对客户的引用。它已初始化为None,表示此商品尚未有客户。代码的工作将为客户分配项目。

以下代码将这些类映射到各自的数据库表。

# SQLAlchemy database transmutation
engine = create_engine('sqlite:///:memory:', echo=False)
metadata = MetaData()

customers_table = Table('customers', metadata,
    Column('uid', Integer, primary_key=True),
    Column('name', String),
    Column('email', String)
)


orders_table = Table('orders', metadata,
    Column('item_id', Integer, primary_key=True),
    Column('item_name', String),
    Column('customer', Integer, ForeignKey('customers.uid'))
)

metadata.create_all(engine)
mapper(Customer, customers_table)
mapper(Order, orders_table)  

现在,如果我做了类似的事情:

for order in session.query(Order):
    print order  

我可以获得这种形式的订单清单:

Item ID 1001: MX4000 Laser Mouse, has been ordered by customer no. 12  

我想要做的是找出客户12的姓名和电子邮件地址(这就是我将ForeignKey用于Customer表的原因)。我该怎么办呢?

根据我的评论更新

我知道这似乎有点无用,但仅仅是为了知道:我需要做些什么来保持关系的单向性?

另外,如果我有另一张外键进入另一张桌子?我该如何更新映射器?

1 个答案:

答案 0 :(得分:5)

首先,如果您确实将客户传递给Order构造函数,那么至少要使用它。 我建议使用默认值,但仍允许在创建时分配给客户,如下所示:

class Order(object):
    def __init__(self, item_id, item_name, customer=None):
        self.item_id = item_id
        self.item_name = item_name
        self.customer = customer # self.customer = None
    #...

为了让您的关系发挥作用,您必须初始化关系 对象之间,FK是不够的。我建议您将代码更改为以下(摘录):

orders_table = Table('orders', metadata,
    Column('item_id', Integer, primary_key=True),
    Column('item_name', String),
    Column('customer_id', Integer, ForeignKey('customers.uid')) # changed
)

# for bi-directional relationship use:
mapper(Customer, customers_table, properties={
    'orders': relationship(Orders, backref='customer')
})
mapper(Orders, orders_table)
# for uni-directional relationship use:
mapper(Customer, customers_table)
mapper(Orders, orders_table, properties={
    'customer': relationship(Customer)
})
#...

然后您可以从订单导航到客户,然后返回:

print mycustomer.orders # in case of bi-directional
print order.customer