Сохранить или обновить для FK отношения Sqlalchemy - PullRequest
2 голосов
/ 27 февраля 2010

Я гуглил, но не смог найти ответ на этот, казалось бы, простой вопрос.

У меня два отношения: клиент и заказ. Каждый заказ связан с одним клиентом и поэтому имеет отношение FK к таблице клиентов. Отношения с клиентами хранят только имена клиентов, и я установил уникальное ограничение для таблицы клиентов, за исключением повторяющихся имен.

Допустим, я создаю новый экземпляр заказа и устанавливаю клиента для заказа. Что-то вроде:

order_instance.customer = Customer("customer name")

Когда я сохраняю экземпляр заказа, SqlAlchemy будет жаловаться, если клиент с таким именем уже существует в таблице клиентов.

Как мне указать SqlAlchemy вставлять в таблицу клиентов, если клиент с таким именем еще не существует, или просто игнорировать (или даже обновлять) отношения с клиентами? Я не хочу каждый раз проверять, существует ли уже клиент с каким-то именем ...

---- Редактировать --- Таблица Customer имеет уникальное ограничение, так что никакие два клиента не могут иметь одинаковые имена. Синглтонед, используя вашу текущую реализацию, выдается IntegrityError. Если клиент с таким именем уже существует, верните этот экземпляр Customer. В противном случае верните новый экземпляр Customer.

Кажется, что SqlAlchemy, независимо от того, существует ли клиент уже или нет, пытается выполнить оператор SQL-вставки в таблицу Customer. Возможно, мои каскады установлены неправильно?

Ответы [ 2 ]

3 голосов
/ 03 марта 2010

Я обычно так делаю:

def get_or_create_customer(customer_name):
    customer = session.query(Customer).get(customer_name)
    if not customer:
       customer = Customer(customer_name)
    return customer

order_instance.customer = get_or_create_customer("Jeff Atwood")

Вы можете добавить это как метод к вашему классу, или вы можете адаптировать __init__ метод вашего класса для этого. Однако я бы рекомендовал против этого, так как лучше четко понимать, что именно вы делаете.

1 голос
/ 07 июня 2010

Я не могу комментировать, но добавить к Singletoned ответ.

Вы должны вызывать функцию только один раз для каждого создаваемого клиента. То есть Вы не можете использовать его таким образом:

.. = get_or_create_customer(order[1].customer_name)
.. = get_or_create_customer(order[2].customer_name)
..
session.commit()

Сбой в случае, если клиент сделал несколько заказов, а клиент еще не в БД, поскольку он попытается создать двух равных клиентов.

много способов исправить этот сценарий .. например иметь insert_orders (..) с get_or_create_customer в качестве вложенной функции и обрабатывать клиентов с помощью set ()

...