Использование Inline в ModelForm в Django Admin
Я хочу проверить поле "многие ко многим" в админке Django, переопределив метод clean.
Эта тема дает способ сделать это, создав ModelForm и затем выполнив очистку там. Однако моя проблема заключается в том, что поле "многие ко многим" является инлайн-полем, т. е. вместо виджета, в котором нужно выбрать несколько элементов, у меня есть табличное инлайн-поле.
Я хотел бы узнать, знает ли кто-нибудь, как добавить инлайны в ModelForm, чтобы я мог сделать очистку и валидацию. Я видел, как люди говорили о inlineformset_factory, но это всегда относилось к views.py, а не к админке (и я не могу понять, как мне вообще переопределить метод clean).
Я добавил часть своего кода ниже:
class ProductVariantForm(ModelForm):
class Meta:
model = ProductVariant
fields = [ 'name',
'price',
]
# I then want to be able to add something like
# inlines = [OptionValueInline,]
# for the inline many-to-many field.
def clean(self):
# Check if list of option_values is ok.
class ProductVariantAdmin(admin.ModelAdmin):
form = ProductVariantForm
Добавление инлайна - это функция самого администратора. Смотрите этот документ для получения дополнительной информации об инлайнах. На самом деле, вы не можете добавить инлайн в обычную форму (или ModelForm
).
Для проверки достоверности данных в инлайн-форме можно использовать свойство form
класса InlineModelAdmin
. Таким образом, вы сможете получить прямой доступ к методу clean
инлайн-формы.
Подробнее, он разделен таким образом, потому что инлайны - это отдельная форма в терминах Django, касающаяся разных данных и выполняющая отдельные запросы. Все они передаются в одном HTTP-запросе, но это все, что их объединяет. Поэтому не имеет смысла использовать main ModelForm
для инлайн-данных.
Мое решение проблемы основано на этом посте.
class ProductVariantOptionValueInlineFormSet(BaseInlineFormSet):
def clean(self):
super().clean()
data = self.cleaned_data
# do whatever validation on data here
class ProductVariantOptionValueInline(admin.TabularInline):
model = ProductVariant.option_values.through
formset = ProductVariantOptionValueInlineFormSet
class ProductVariantAdmin(admin.ModelAdmin):
inlines = [
ProductVariantOptionValueInline,
]
exclude = ('option_values',)