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

37,288

Solution 1

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 'initial' not in kwargs:
        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)

Solution 2

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'}

Solution 3

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;

Share:
37,288
Martijn de Milliano
Author by

Martijn de Milliano

I am a prototype engineer and problem solver. In my work I use my 'glue' skills, multi-language software experience and practical hardware knowledge to make heterogeneous systems work together. I can dig deep into complex problems until I find a good solution. I like to ask the one question that discovers the bug. I combine structured programming skills with a getting-the-job-done mentality and enjoy working in an ambitious team. My aim is to create simple and elegant solutions to relevant problems where quality and reliability is essential to succeed. Over the years I have gained experience in developing various types of software: from the on-board software for the flight computer of a sounding rocket to mobile apps to data processor systems for handling big data. I know how to make drivers to connect software to all kinds of devices: from commercial radar systems to cameras to maritime navigation systems and controllers for stepper motors. I like the thrill of making something work: when a message appears on the other end of the line, when the LED blinks on your command, when you wave your hand across a sensor and you see it on your screen, when the parachute deploys from the rocket at exactly the right moment. Right now I am working on the world's first AppScooter at Bolt Mobility: the Dutch Tesla on Two Wheels. This is a exciting challenge that combines the worlds of automotive with smartphones and the internet. Needless to say, software plays a major role here and I am happy to be in the middle of it. In addition, I specified the electronics for the cockpit, from internet modem to Android platform to LED drivers and co-designed the schematics in close cooperation with the electrical engineers. This requires a combination of electrical engineering, mechanical engineering and software skills. You need to be a jack of all trades (the downside is you are master of none), and in this role I really thrive.

Updated on June 22, 2021

Comments

  • Martijn de Milliano
    Martijn de Milliano almost 3 years

    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?