Search code examples
pythondjangodjango-formsdjango-admin

Django's Inline Admin: a 'pre-filled' field


I'm working on my first Django project, in which I want a user to be able to create custom forms, in the admin, and add fields to it as he or she needs them. For this, I've added a reusable app to my project, found on github at:

https://github.com/stephenmcd/django-forms-builder

I'm having trouble, because I want to make it so 1 specific field is 'default' for every form that's ever created, because it will be necessary in every situation (by the way my, it's irrelevant here, but this field corresponds to a point on the map).

An important section of code from this django-forms-builder app, showing the use of admin.TabularInline:

#admin.py
#...
class FieldAdmin(admin.TabularInline):
    model = Field
    exclude = ('slug', )


class FormAdmin(admin.ModelAdmin):
    formentry_model = FormEntry
    fieldentry_model = FieldEntry

    inlines = (FieldAdmin,)
#...

So my question is: is there any simple way to add default (already filled fields) for an admin 'TabularInline' in the recent Django versions? If not possible, I would really appreciate a pointer to somewhere I could learn how to go about solving this.

Important: I've searched for similar questions here and even googled the issue. I've found some old questions (all from 2014 or way older) that mention this possibility not being directly provided by Django. The answers involved somewhat complex/confusing suggestions, given that I'm a Django begginer.


Solution

  • There are a couple of ways to achieve this.

    1: Set a default on the field in the model.

    Django's dynamic admin forms and inlines are smart enough to detect this and display it automatically as a default choice or entry.

    class Book(models.Model):
    
        rating = models.IntegerField(default=0)
    

    2: Use a custom form in your TabularInline class.

    class BookInlineForm(models.ModelForm):
    
        class Meta:
            model = Book
            fields = ('rating', )
    
        def __init__(self, *args, **kwargs):
            initial = kwargs.pop('initial', {})
            # add a default rating if one hasn't been passed in
            initial['rating'] = initial.get('rating', 0)
            kwargs['initial'] = initial
            super(BookInlineForm, self).__init__(
                *args, **kwargs
            )
    
    
    class BookTabularInline(admin.TabularInline):
        model = Book
        form = BookInlineForm
    
    
    class ShelfAdmin(admin.ModelAdmin):
        inlines = (BookAdmin,)