Зачем мне сохранять эту модель перед добавлением в другую?
Вопрос
В Django я пытаюсь сделать что-то вроде этого:
# if form is valid ...
article = form.save(commit=False)
article.author = req.user
product_name = form.cleaned_data['product_name']
try:
article.product = Component.objects.get(name=product_name)
except:
article.product = Component(name=product_name)
article.save()
# do some more form processing ...
Но тогда это говорит мне:
нулевое значение в столбце " product_id " нарушает ненулевое ограничение
Но я не понимаю, почему это проблема. Когда вызывается article.save ()
, он должен иметь возможность создать продукт then (и сгенерировать идентификатор).
Я могу обойти эту проблему, используя этот код в блоке кроме
:
product = Component(name=product_name)
product.save()
article.product = product
Но причина, по которой меня это беспокоит, заключается в том, что если article.save ()
завершится неудачей, он уже создал новый компонент / продукт. Я хочу, чтобы они преуспели или потерпели неудачу вместе.
Есть ли хороший способ обойти это?
Решение
Вы можете обойти это, используя:
target_product, created_flag = Component.objects.get_or_create(name=product_name)
article.product = target_product
я уверен, что get_or_create ()
установит идентификатор объекта, если он должен его создать.
Кроме того, если вы не возражаете против пустых отношений FK в таблице Article, вы можете добавить null = True
к определению.
Другие советы
Принцип работы Django ManyToManyField заключается в том, что он создает дополнительную таблицу. Скажем, у вас есть две модели, ModelA и ModelB. Если вы сделали ...
ModelA.model_b = models.ManyToManyField(ModelB)
Что Django на самом деле делает за кулисами, так это создает таблицу ... app_modela_modelb
с тремя столбцами: id
, model_a_id
, model_b_id код>.
Держите эту мысль в уме. Что касается сохранения ModelB, Django не присваивает ему идентификатор, пока он не будет сохранен. Технически вы можете вручную назначить ему идентификатор и избежать этой проблемы. Кажется, вы позволяете Django обрабатывать то, что вполне приемлемо.
У Джанго проблемы с M2M. Зачем? Если у ModelB еще нет идентификатора, что будет в столбце model_b_id
в таблице M2M? Ошибка для нулевого product_id
, скорее всего, является ошибкой нулевого ограничения для поля M2M, а не для идентификатора записи ModelB.
Если вы хотите, чтобы они "преуспели вместе" или "потерпеть неудачу вместе" возможно, пришло время заняться транзакциями. Вы, например, заключаете все это в транзакцию и выполняете откат в случае частичного сбоя. Я не проделал большую работу лично в этой области, так что, надеюсь, кто-то еще поможет в этой теме.
Нет смысла включать фрагмент кода в транзакции, так как вы должны прочитать Документация Django , чтобы получить хорошее понимание.