【问题标题】:Use a foreign key mapping to get data from the other table using Python and SQLAlchemy使用外键映射使用 Python 和 SQLAlchemy 从另一个表中获取数据
【发布时间】:2010-05-27 15:09:13
【问题描述】:

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

基本上,我已经使用 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)  

上面基本上是一个简单的客户,有一个 id、一个名字和一个电子邮件地址。

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 的姓名和电子邮件地址(这就是我在 Customer 表中使用 ForeignKey 的原因)。我该怎么做?

根据我的评论更新

我知道这似乎有点无用,但只是为了知道:我必须做些什么才能保持单向关系?

另外,如果我有另一个外键进入另一个表?我将如何更新映射器?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    首先,如果您确实将 customer 传递给 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
    

    【讨论】:

    • 只是验证一件事。我知道它违背了目的,但如果我希望关系是单向的 - 我将如何更改您建议的映射器?刚刚在原文中又增加了两个问题。
    • 有关关系的文档,请参见:sqlalchemy.org/docs/mappers.html#relationship-configuration。此外,我会将 Orders 对象重命名为 Order。
    • 您评论中的链接现已损坏。目前是here
    猜你喜欢
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多