Passing parameters to inline form in django admin

4.4k Views Asked by At

I have an admin class inheriting from ModelAdmin:

class TemplateAdmin (admin.ModelAdmin):
    inlines = (TemplateAttributeInline, CompanyAttributeInline)
    list_display = ("name", "created", "updated","departments")
    list_filter = ['companies__company']
    list_editable = ("departments",)
    search_fields = ("name", "companies__company",)
    exclude = ("companies",)
    save_as = True

I want to pass a parameter to TemplateAttributeInline which will in turn then pass the parameter to TemplateAttributeForm. What is the best way to do this?

TemplateAttributeInline:

class TemplateAttributeInline (admin.TabularInline):
    model = TemplateAttribute
    extra = 0
    sortable_field_name = "display"
    form = TemplateAttributeForm

TemplateAttributeForm

class TemplateAttributeForm(forms.ModelForm):
    class Meta:
        model = Template
    def __init__(self,*args, **kwargs):
        super(TemplateAttributeForm, self).__init__(*args, **kwargs) 
        self.fields['attribute'].queryset = Attribute.objects.filter(#WANT TO FILTER BY THE ID OF THE COMPANY THAT OWNS THE TEMPLATE WE ARE EDITING ON THE ADMIN PAGE)
2

There are 2 best solutions below

1
On BEST ANSWER

You can create a function that returns a class for the form:

def TemplateAttributeForm(param):

    class MyTemplateAttributeForm(forms.ModelForm):
        class Meta:
            model = Template
        def __init__(self,*args, **kwargs):
            super(TemplateAttributeForm, self).__init__(*args, **kwargs) 
            #do what ever you want with param

    return MyTemplateAttributeForm

Use it in another funtion to define the TemplateAttributeInline

def TemplateAttributeInline(param):

        class MyTemplateAttributeInline (admin.TabularInline):
            model = TemplateAttribute
            extra = 0
            sortable_field_name = "display"
            form = TemplateAttributeForm(param)

        return MyTemplateAttributeInline 

To finish, use this function in your TemplateAdmin definition:

class TemplateAdmin (admin.ModelAdmin):
    inlines = (TemplateAttributeInline(param), CompanyAttributeInline)
    ....
0
On

To complement the response by Sylvain Biehler, I added the following code to make the inline form dynamic. Here is the reference at django doc. The method "get_inline_instances" is called on first time "loading", after "saving", and on "reloading". On "add" events, None is passed.

Here, "obj" is the model instance the admin form is currently bound to. It is "None" for unbound (add new) forms. Instead of directly passing the model instance "obj", you can pass any attribute of it, e.g. obj.id. In this case, you need to first check if the instance is not None.

class TemplateAdmin (admin.ModelAdmin):
   ...
   inlines = (TemplateAttributeInline(param), CompanyAttributeInline)
   ...
   def get_inline_instances(self, request, obj=None): 
     return  [
         TemplateAttributeInline(obj)(self.model, self.admin_site), 
         CompanyAttributeInline(self.model, self.admin_site), 
       ]