'How to set default values in TabularInline formset in Django admin
How to set first default rows/values in django admin's inline?
class Employee(models.Model):
username = models.CharField(_('Username'), max_length=150, null=False, blank=False)
email = models.CharField(_('Email'), max_length=150, null=False, blank=False)
class Details(models.Model):
employee = models.ForeignKey(Employee, verbose_name=_('Employee'), blank=False, null=False)
label = models.CharField(_('Label'), max_length=150, null=False, blank=False)
value = models.CharField(_('Value'), max_length=150, null=False, blank=False)
class DetailsFormset(forms.models.BaseInlineFormSet):
def __init__(self, *args, **kwargs):
self.initial = [
{ 'label': 'first name'},
{'label': 'last name'},
{'label': 'job',}]
super(DetailsFormset, self).__init__(*args, **kwargs)
class DetailsInline(admin.TabularInline):
model = Details
formset = DetailsFormset
fieldsets = [
['', {'fields': ['employee', 'label', 'value']}]
]
class EmployeeAdmin(admin.ModelAdmin):
inlines = [DetailsInline]
but this row doesn't work
self.initial = [
{ 'label': 'first name'},
{'label': 'last name'},
{'label': 'job',}]
How do I set default values using django admin?
Solution 1:[1]
If what you need is to define default values for the new forms that are created you can redefine the empty_form property of a InlineFormSet:
class MyDefaultFormSet(django.forms.models.BaseInlineFormSet):
@property
def empty_form(self):
form = super(MyDefaultFormSet, self).empty_form
# you can access self.instance to get the model parent object
form.fields['label'].initial = 'first name'
# ...
return form
class DetailsInline(admin.TabularInline):
formset = MyDefaultFormSet
Now, every time you add a new form it contains the initial data you provided it with. I've tested this on django 1.5.
Solution 2:[2]
I tried many suggestions from Stackoverflow (Django=4.x), not working for me. Here is what I did.
class MilestoneFormSet(forms.models.BaseInlineFormSet):
model = Milestone
def __init__(self, *args, **kwargs):
super(MilestoneFormSet, self).__init__(*args, **kwargs)
if not self.instance.pk:
self.initial = [
{'stage': '1.Plan', 'description': 'Requirements gathering', },
{'stage': '2.Define', 'description': 'Validate requirement', },
]
class MilestoneInline(admin.TabularInline):
model = Milestone
formset = MilestoneFormSet
def get_extra(self, request, obj=None, **kwargs):
extra = 0 #default 0
if not obj: #new create only
extra = 2 #2 records defined in __init__
return extra
I hope this works for everyone.
Solution 3:[3]
To provide a static default for all instances in the inline, I found a simpler solution that just sets it in a form:
class DetailsForm(django_forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['label'] = 'first_name'
class DetailsInline(admin.TabularInline):
form = DetailsForm
# ...
I think this doesn't work for the OP's particular case because each form has a different value for the 'label' field, but I hope it can be useful for anyone coming to this page in the future.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Code-Apprentice |
| Solution 2 | AndyC |
| Solution 3 | Code-Apprentice |
