Django Gotcha – Inline Foriegn Key Fields
Working on a project recently, I came across an interesting gotcha in using inline foreign keys in the Django admin. Apparently the objects described by the inline fields are saved after the parent object is saved. This becomes important if you try and do anything with the child objects as part of the parent object’s save method.
To illustrate this let’s use an example. For this example we will use ClassA and ClassB. ClassB includes a foreign key to ClassA and it is set to display inline in the admin. In ClassA’s model we are also overriding ClassA’s save function. In this new save function we are performing a variety of tasks. Next let’s say as one of these tasks we delete all of the child objects (ClassB) related to the parent (ClassB) and then recreate them based on some property of the parent. Now if we go into the admin and edit the parent we will get an interesting result. In our inline fields we will see both the new child objects we created as well as all of the old objects we deleted. This obviously can be a rather confusing result. If we print out the child objects in the database at the end of our new save function we will only see our new objects, this leads us to ask where are the old objects coming from? As it turns out the inline fields are processed after our save function completes so even though we deleted our old child objects in our save function they get re-created when the old data in the inline fields gets processed.
Unfortunately at this time I have not found a good solution to this gotcha other than leaving the child objects in their standard editing form and removing the edit inline option. Have a better solution for this situation? Let me know, leave a comment!

Just thinking out loud, but perhaps you can achieve a good result using signals ?
I don’t really think signals are going to help.
The issue is that his code is executing after the parent object is saved, but before his child objects are saved, so they’re written right over the top of whatever his code does. From what I can tell from the docs, the ‘post_save’ signal does the same thing.
You could listen for post_save signals from each of the child objects, but then your code runs once for each of them, and there’s no good way to know you’re looking at the last one.
IMHO, the best shot might be to try to hook it into the admin.
Perhaps, I have tried using the post-save signal and it definitely runs before the children get processed.
Thanks for the feedback!
Sean O'Connor said this on January 21, 2008 at 10:46 am |
As a lot of other people I’ve also come across this problem. I’ve found it possible however to add hooks in newforms to be able to perform stuff after related objects are saved. newforms-admin branch is required to make it work in admin. I should perhaps write about it somewhere..
I am currently working with the newforms-admin branch so I’d be very interested to see your solution.
Sean O'Connor said this on January 21, 2008 at 2:50 pm |
Ok, I made some use of that old blog and now there’s a post describing this with a patch for the current newforms-admin branch. http://simonsay.wordpress.com/2008/01/23/hooks-for-m2m-fields-and-inline-formsets-in-django-newforms/