Django 内联模型表单集和内联模型表单处理初始值的方式不同

Django inline model formset and inline model form handle initial differently

我正在使用 StackedInline 来填充 OneToOneField,但我想让它成为可选的,所以我设置了 min_num=0 和 extra = 0。

我还想在用户按下“➕添加另一个”按钮时包含默认值。

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        kwargs['initial'] = {'hello': 'world'}

class MyInline(admin.StackedInline):
    form = MyForm
    extra = 0
    min_num=0

这行得通。当有人按下“➕ 添加另一个”按钮时,hello 字段会填充 world

我也想做一些自定义验证,所以看起来我必须使用 BaseInlineFormSet。我把最初的东西移到了 MyFormSet.__init__

class MyFormSet(BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if not self.forms:
            return
        self.forms[0].fields['hello'].initial = 'world'
        
    def clean(self):
        # My custom validation

class MyInline(admin.StackedInline):
    formset = MyFormSet
    extra = 0
    min_num=0

但是当用户按下“➕添加另一个”按钮时不再填充初始值,只有当表单最初显示为 extra = 1.

我还需要在 MyFormSet 中做些什么来保持 MyForm 的行为吗?

问题

您不能尝试在表单集的 __init__ 中设置 initial 属性,因为那时 self.forms[0] 甚至不存在。执行此操作的正确位置是(如您的第一个)示例,在 MyForm.

的 init 方法中

解决方案

你可以做的是使用MyFormSet使用clean实现自定义验证,并使用MyForm添加关于默认值的逻辑,然后:

from django.forms import formset_factory

class MyInline(admin.StackedInline):
    form = Myform
    formset = MyFormSet
    extra = 0
    min_num=0