Reputation: 8309
One of my models has a field with a default value that I'm happy with, but I want that default value to be different within the admin. Here's my attempt at achieving this:
from django.db import models
class Parent(models.Model):
parent_field_1 = models.CharField(max_length=255)
parent_field_2 = models.CharField(max_length=255, blank=True)
class Meta:
ordering = ('pk',)
def __unicode__(self):
return self.parent_field_1
class Child(models.Model):
parent = models.ForeignKey(Parent)
child_field_1 = models.CharField(max_length=255)
child_field_2 = models.CharField(max_length=255, blank=True)
child_field_3 = models.IntegerField(default=0)
class Meta:
ordering = ('pk',)
verbose_name_plural = 'children'
def __unicode__(self):
return self.child_field_1
from django import forms
from .models import Child
class ChildForm(forms.ModelForm):
class Meta:
model = Child
fields = [
'parent',
'child_field_1',
'child_field_2',
'child_field_3',
]
def __init__(self, *args, **kwargs):
if 'instance' not in kwargs:
initial = kwargs.get('initial', {})
initial['child_field_3'] = '1'
kwargs['initial'] = initial
super(ChildForm, self).__init__(*args, **kwargs)
from django.contrib import admin
from .forms import ChildForm
from .models import Parent, Child
class ChildInline(admin.StackedInline):
model = Child
form = ChildForm
class ParentAdmin(admin.ModelAdmin):
inlines = [ChildInline]
class ChildAdmin(admin.ModelAdmin):
form = ChildForm
admin.site.register(Parent, ParentAdmin)
admin.site.register(Child, ChildAdmin)
When I go to add a child, the "Child field 3" field is populated with "1" (instead of the model's default of "0"), which is what I want. When I go to edit a child, the "Child field 3" field is populated with whatever value is in the database, which is also what I want.
The problem I'm running into comes in when I go to add or edit a parent. If I try to add a parent, I am required to also fill out all of the child inline forms. Likewise, if I try to edit a parent, I am required to fill out all of the extra child inline forms. If I comment out the ChildInline
class' form = ChildForm
line, I get the correct behavior, but, of course, the incorrect default value ("0" instead of "1"). How can I get the correct behavior and the correct default value?
Upvotes: 4
Views: 2092
Reputation: 34942
Your field is an IntegerField
. You must set initial
to an integer.
When the form is permitted to be empty (which is the case here), full_clean
is dismissed if the form did not change. has_changed()
is determined by the emptiness of changed_data
.
Field changes is determined by field.has_changed(initial, data)
where data is passed through field.to_python(value)
, which returns an integer in the case of an IntegerField
. On the other hand, initial
is supposed to be of the right type and is kept as provided. This leads to a comparison: has_changed = ('1' != 1)
, which returns True
, while you expected it to return False
.
Upvotes: 2