Проверка нескольких внешних ключей при сохранении формы ModelForm
Пояснение:
У меня есть модель, которая имеет два внешних ключа:
class Book(models.Model):
name = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=CASCADE)
created_by = models.ForeignKey(User, blank=True, null=True, on_delete=CASCADE)
У меня есть модельная форма для этого:
class BookForm(modelForm):
class Meta:
model = Book
exclude = ('author', 'created_by',)
В моей бизнес-логике я хочу сохранить нового автора и книгу с ним в одном представлении, а created_by
в некоторых случаях может быть null. Поэтому, прежде чем сохранить экземпляр BookForm, я сначала создам автора. Итак, предположим, что я создал автора, тогда для сохранения книги я сделаю следующее:
f = BookForm(post_data)
if form.is_valid():
instance = f.save(commit=False)
instance.author = author
instance.created_by = user
instance.save()
То, что я сделал до сих пор, работает нормально, но поля внешнего ключа не являются частью валидации. Как видно из класса модели, поле author
является обязательным, а поле created_by
- необязательным. Поэтому, если я хочу добавить некоторые валидации для них, я должен добавить их явно, настроив метод is_valid()
, или добавив некоторые if
условия перед instance.author = author
.
Вопрос:
Большая картина заключается в том, что у меня есть модель с гораздо большим количеством внешних ключей; некоторые из них являются обязательными, а другие - нет. Поэтому, используя тот же подход, что и выше, я должен добавить пользовательскую валидацию для каждого FK в явном виде, что я считаю дублированием и нечистотами, поскольку валидация этих полей FK определена в классе моей модели
Итак, какова наилучшая практика для автоматической проверки множественных внешних ключей при сохранении, проверяя проверку моделей напрямую и не упоминая каждый FK по одному?
Поскольку поля внешнего ключа не включены в вашу форму, для них не будет никакой валидации формы. Вам нужна валидация модели.
Django предоставляет метод model.full_clean()
, который выполняет все шаги по проверке модели.
Вам придется вызвать метод вручную, поскольку метод save() не вызывает никакого метода очистки модели.
См. документацию здесь.
Например,
f = BookForm(post_data)
if form.is_valid():
instance = f.save(commit=False)
instance.author = author
instance.created_by = user
try:
instance.full_clean()
except ValidationError as e:
# Do something based on the errors contained in e.message_dict.
# Display them to a user, or handle them programmatically.
pass
instance.save()