Admin Inline empty extra - how to access parent form model ID?

2,462 views
Skip to first unread message

mixit

unread,
Apr 28, 2010, 5:48:31 AM4/28/10
to Django users
Using an Inline in an Admin form:
The main Form model has various text fields, and one Inline, using a
custom little form of its own.
The Inline model has an parentFK pointing to the parent Form model and
has an different FK to a large table, which is displayed as a popup
(or dropdown) menu with ALL its entries - all works perfectly :o)

I want to filter the Inline's FK popup menu (because its too large) by
the ID of the parent model instance (plus various other factors).

Working part of the Implementation:
A "populated" (i.e. already 'saved') inline has an instance, thus I
can access the parentFK from the Inline via 'self.instance.parentFK"
and filter the popup menu by filtering its queryset... again works
perfectly :o)

Problem:
The Inline has 'extra: 1' set, to give me one empty extra Inline.
This empty extra however has NO instance before saving (i.e.
self.instance is None), therefore I cannot use the above technique to
get to its parent model, so I cannot filter its popup menu as before :
(

Horrible hack workaround:
use formfield_for_foreignkey(),
hunt for the popup field name,
grab the request.META['PATH_INFO']
regexp it and pull out the parent model ID.
finally, use the parent model ID thus acquired to filter the popup
menu queryset.

Question:
Is there no other way to access the parent Form model ID from an
unsaved, "empty" Inline?

I've spent a couple of days wading through the Admin code but can't
find anyway for an empty, "extra" Inline to know anything about the
form model it is embedded in...

Can anyone advise if there is some nifty field, attribute or function
that I am missing?
regards
si

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Daniel Roseman

unread,
Apr 28, 2010, 8:55:26 AM4/28/10
to Django users
The inline formset itself (rather than its forms) has an "instance"
attribute which refers to the instance of the parent form.
--
DR.

mixit

unread,
Apr 28, 2010, 12:58:20 PM4/28/10
to Django users
Ah, ok, this isgetting interesting; the formset, eh?
I'm guessing I get to the formset from the parentForm somehow...
Right, I shall start poking around and see if I can find the link.
Many thanksfor the pointer!
Regards,
si

Dominique Guardiola Falco

unread,
May 31, 2012, 6:53:05 AM5/31/12
to django...@googlegroups.com


On Wednesday, April 28, 2010 2:55:26 PM UTC+2, Daniel Roseman wrote:

The inline formset itself (rather than its forms) has an "instance"
attribute which refers to the instance of the parent form.

Sorry to bring back a two-years old post, but is there still a way to do this in django 1.4 ?
I'm exploring the BaseInlineFormset object but there's no "instance" attribute anymore

Dominique Guardiola Falco

unread,
May 31, 2012, 10:25:10 AM5/31/12
to django...@googlegroups.com
I found a noce solution, it only needs this tiny patch already proposed on the tracker :
https://code.djangoproject.com/ticket/17856
There's no reason this patch could not be merged in the trunk, it's self-contained

With this, I can override get_inline_instances in my ModelAdmin :

    def get_inline_instances(self, request, obj):
        inline_instances = []
        for inline_class in self.inlines:
            if inline_class.model == get_model('coop_local', 'Exchange'):
                inline = inline_class(self.model, self.admin_site, obj=obj)
            else:
                inline = inline_class(self.model, self.admin_site)
            inline_instances.append(inline)
        return inline_instances

The inline gets the obj parameter , puts it in a local attribute and deletes it to not bother the Inline superclass

class ExchangeInline(admin.StackedInline):

    def __init__(self, *args, **kwargs):
        self.parent_object = kwargs['obj']
        del kwargs['obj']  # superclass will choke on this
        super(ExchangeInline, self).__init__(*args, **kwargs)

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'location':
            kwargs['queryset'] = self.parent_object.locations()
        return super(ExchangeInline, self).formfield_for_dbfield(db_field, **kwargs)

An finally in formfield_for_dbfield I can use parent_object to correctly filter my queryset, and this filtering works in any line of the formset : those which are bound to existing objects and the blank (extra ) ones !



Reply all
Reply to author
Forward
0 new messages