Используйте сопоставление внешнего ключа для получения данных из другой таблицы с использованием Python и SQLAlchemy - PullRequest
4 голосов
/ 27 мая 2010

Хм, название было сложнее сформулировать, чем я думал.

По сути, эти простые классы сопоставлены с таблицами с использованием 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, который просто содержит информацию о заказе: идентификатор, имя и ссылку на клиента. Он инициализирован на 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 Ответ

5 голосов
/ 27 мая 2010

Прежде всего, если вы передадите клиента в Конструктор заказов, то хотя бы воспользуйтесь им. Я предлагаю использовать значение по умолчанию, но все же разрешить назначение клиенту при создании, как показано ниже:

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
    #...

Чтобы ваши отношения работали, вы должны инициализировать отношения между объектами ФК недостаточно. Я предлагаю вам изменить свой код следующим образом (выдержки):

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...