ModelAdmin: trying to override get_formset()

So, I have a custom ModelAdmin with an inline. I want it to use a particular formset. In the documentation I found get_formset(). The documentation unfortunately isn’t helpful at all. It points to an example that uses get_formset_with_inlines() which looks nothing like get_formset(). get_formset() is supposed to return a BaseFormSet. The return statement of the orignal method looks like this:
return return inlineformset_factory(self.parent_model, self.model, **defaults)
However, when I try to just return the InlineFormSet of my choice, I get the following error:

init() got an unexpected keyword argument ‘instance’

In the traceback there ist no reference to code that I wrote myself. The get_formset() method is rather complex with a class defnition inside the method. I’m not sure I grasp all the concepts in there. Did I chose the wrong hook? Is there another way to pass an InlineFormSet to an InlineModelAdmin?

EDIT: I already tried setting the formset via InlineModeAdmin.formset with the same error.

What confused me the first time I tried to use get_formset is that get_formset is supposed to return a class and not an instance of a class. IIRC, that error is what happens when you return an instance from that method.

If you chase through the base classes in the Django source code, you’ll see that it builds a Model FormSet class to be returned, but doesn’t make an instance of that class at that point. (You really only need to look at what the functions are returning to get a “feel” for what’s going on.)

Ok, thanks again, this cleared something up. Depending on what parameters you pass to the inlineformset_factory it returns the class or an instance of the class. This is obvious to me now, but before for some reason I had stored in my head that these factories only return classes.

So this is still related to adding fields to a ModelForm in the Admin. With what you helped me with, I was able to add fields to an AdminForm. However, when I used that Admin as an inline for another admin, the fields would not be displayed. I then discovered the method add_fields() for formsets. However, I have not found the appropriate place to use it. For most of the hooks that I’ve found, the formset was yet a class. Then there were some protected methods, where the action happened. I tried this:

def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
    inline_admin_formsets = context['inline_admin_formsets']
    inline_admin_formset = inline_admin_formsets[0]
    formset = inline_admin_formset.formset
    formset.add_fields(self.form(request), 0)
    inline_admin_formset.formset = formset
    context['inline_admin_formsets'] = [inline_admin_formset]

    return super().render_change_form(request, context, add=add, change=change, form_url=form_url, obj=obj)

It didn’t work. So this is still the problem with the JSON field being replaced by custom fields. Unless you have another bright idea, I think I will just add a custom form to my ModelAdmin. I think adding fields is really not intended… Too bad.

<sarcasm>

(Emphasis mine)

Well, evidently, I haven’t had the first one yet, 'cause it didn’t work.
</sarcasm>

I know you probably need to be moving forward with your project. Unfortunately, I’m not going to have any time over the next three days to do any experimenting in that area. But it is an interesting enough topic for me to maybe come back to this next week. (Yes, probably moot by that time, but I tend not to let things go once I get interested in finding something out.)

Ken

1 Like