How to set initial data for Django admin model add instance form?

Go To StackoverFlow.com

18

How can I set an initial value of a field in the automatically generated form for adding a Django model instance, before the form is displayed? I am using Django 1.3.1.

My model is the following:

class Foo(models.Model):
  title = models.CharField(max_length=50)
  description = models.TextField()

and the current admin form is really nothing special

class FooAdmin(admin.ModelAdmin):
  ordering = ('title',)

When I use the admin page to add a new instance of Foo, I get a nice form with empty fields for title and description. What I would like is that the description field is set with a template that I obtain by calling a function.

My current best attempt at getting there is this:

def get_default_content():
  return 'this is a template for a Foo description'

class FooAdminForm(django.forms.ModelForm):

  class Meta:
      model = Foo

  def __init__(self, *args, **kwargs):
      kwargs['initial'].update({'description': get_default_content()})
      super(FooAdminForm, self).__init__(self, *args, **kwargs)

class FooAdmin(admin.ModelAdmin):
  ordering = ('title',)
  form = FooAdminForm

but if I try this I get this Django error:

AttributeError at /admin/bar/foo/add/ 
   'FooForm' object has no attribute 'get'
Request Method: GET
Request URL:    http://localhost:8000/admin/bar/foo/add/
Django Version: 1.3.1
Exception Type: AttributeError
Exception Value:    'FooForm' object has no attribute 'get'
Exception Location: /www/django-site/venv/lib/python2.6/site-packages/django/forms/widgets.py in value_from_datadict, line 178

I don't know what is wrong here, and what I should do to make it work. What I also find strange about this error (apart from the fact that I see it at all) is that there is no FooForm in my code at all?

2012-04-03 20:32
by Martijn de Milliano


20

You need to include self as the first argument in your __init__ method definition, but should not include it when you call the superclass' method.

def __init__(self, *args, **kwargs):
    # We can't assume that kwargs['initial'] exists! 
    if not kwargs.get('initial'):
        kwargs['initial'] = {}
    kwargs['initial'].update({'description': get_default_content()})
    super(FooAdminForm, self).__init__(*args, **kwargs)

Having said that, a model field can take a callable for its default, so you may not have to define a custom admin form at all.

class Foo(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField(default=get_default_content)
2012-04-03 21:16
by Alasdair
Wow, that worked like a charm! Awesomely cryptic message by the way for such a silly mistake... Thanks a lot for your help - Martijn de Milliano 2012-04-04 17:53
By the way, I also tried your second suggestion successfully, which is even cleaner, so thanks again - Martijn de Milliano 2012-04-04 17:55
I found that setting kwargs['initial'] caused an error when saving the form. I had set an if clause:

if 'initial' in kwargs.keys():
  kwargs['initial'].update(...

This worked for displaying the initial values and updating them - Sven 2012-12-17 14:11

@Sven good point. I've updated my answer to set initial to an empty dict if it isn't in kwargs - Alasdair 2012-12-17 15:47


22

Alasdair's approach is nice but outdated. Radev's approach looks quite nice and as mentioned in the comment, it strikes me that there is nothing about this in the documentation.

Apart from those, since Django 1.7 there is a function get_changeform_initial_data in ModelAdmin that sets initial form values:

def get_changeform_initial_data(self, request):
    return {'name': 'custom_initial_value'}
2015-11-11 10:37
by Wtower
for some reason in 1.10.2 this method is not called at all, though it is present in the doc - scythargon 2016-10-25 11:46
@scythargon I just tested it in 1.10.2 and for me it worked as documented - Wtower 2017-03-16 17:36
It's easy to lose track of all the available hooks for ModelAdmin. Thanks for this - Filip Kilibarda 2017-12-27 21:24
Django 1.11.10 and Django didn't call overrided getchangeforminitial_data method - valex 2018-04-01 17:43
Facing the same issue of the method not being called I dove into the source code. The answer is quite simple, it is only called for newly created objects. Changing an existing object will not call it - Fynn Becker 2018-08-09 15:20


9

More then 3 years later, But actually what you should do is override admin.ModelAdmin formfield_for_dbfield .. like this:

class FooAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        field =  super(FooAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'description':
            field.initial = 'My initial description'
        elif db_field.name == 'counter':
            field.initial = get_counter() + 1
        return field

Cheers;

2015-06-28 01:16
by Ramez Ashraf
Very nice. It is strange but there is no such thing in the documentation: https://docs.djangoproject.com/en/1.8/ref/contrib/admin - Wtower 2015-11-11 10:34
The Django admin is "way" under-documented , unfortunately - Ramez Ashraf 2015-11-21 09:50
Alternatively you could remove the field = super... line, set kwargs['initial'] = 'My initial description' (and similar for the 'counter' field), followed by return super... That saves a line - djvg 2019-02-19 20:30