Reputation: 1342
I'm using a StackedInline to populate a OneToOneField, but I want to make it optional, so I set min_num=0 and extra = 0.
I also want to include default values when the user presses the "➕ Add another" button.
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
kwargs['initial'] = {'hello': 'world'}
class MyInline(admin.StackedInline):
form = MyForm
extra = 0
min_num=0
This works. When someone presses the "➕ Add another" button, the hello
field is populated with world
.
I also want to and do some custom validation, so it looks like I have to use BaseInlineFormSet. I moved the initial stuff to 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
But the initial values are no longer populated when the user presses the "➕ Add another" button, only when the form is initially displayed with extra = 1
.
Is there another thing I need to do in MyFormSet to preserve the MyForm behavior?
Upvotes: 0
Views: 160
Reputation: 6825
You can't try and set the initial
property in the __init__
of your formset, since self.forms[0]
doesn't even exist at that point. The correct place to do this is (as in your first) example, in the init method of your MyForm
.
What you can do is use MyFormSet
to implement your custom validation using clean
, and use MyForm
to add the logic about default values, then:
from django.forms import formset_factory
class MyInline(admin.StackedInline):
form = Myform
formset = MyFormSet
extra = 0
min_num=0
Upvotes: 1