Possible bug with admin inlines

84 views
Skip to first unread message

Martin Ostrovsky

unread,
Mar 5, 2012, 6:06:10 PM3/5/12
to django-d...@googlegroups.com
Hello,

I have come across this issue in Django v1.2.5, just test it on 1.4rc1 and can still reproduce. Not sure if it's a bug or a case of "don't do that". But here goes.

Here's the models.py:


Here's the admin.py:


So what we have are 3 models. Two models, B & C, have foreign keys to A. In addition, C has a foreign key to B. We create stacked inlines of B & C in A. Here's some fixture data to load & test:


If you try to delete an instance of B via the inline delete checkbox, you get a validation error:

Exception Type: ValidationError at /admin/web/a/1/
Exception Value: [u'Select a valid choice. That choice is not one of the available choices.']

Now I get what's happening (I think), B gets deleted first, then the formset validation for C runs, tries to validate the drop down choice, and fails since B has already been deleted.

What do you guys think? Is this a bug or a really really small corner case that most people will never stumble upon? 


Danny Adair

unread,
Mar 5, 2012, 6:15:18 PM3/5/12
to django-d...@googlegroups.com
On Tue, Mar 6, 2012 at 12:06, Martin Ostrovsky
<martin.o...@gmail.com> wrote:
>[...]

> Now I get what's happening (I think), B gets deleted first, then the formset
> validation for C runs, tries to validate the drop down choice, and fails
> since B has already been deleted.
>
> What do you guys think? Is this a bug or a really really small corner case
> that most people will never stumble upon?

Just want to add that's not the only place where this can happen.
If you hook into the post_delete() delete signal of a model with a FK,
your method can't access the FK object if it's a cascaded delete
invoked by the FK object's delete().
I always wondered why children don't get deleted first (which is how
the database _has_ to do it anyway).
My workaround is to delete in the correct order myself but I wish I
didn't have to.

Cheers,
Danny

Martin Ostrovsky

unread,
Mar 5, 2012, 6:21:44 PM3/5/12
to django-d...@googlegroups.com
Danny reading your reply gave me an idea to try and it worked.

I switched the order of the inlines. So I put C first, then B. This way C validates properly, then B is deleted and the cascaded deletion deletes C and everything works as expected.

Danny Adair

unread,
Mar 5, 2012, 6:44:24 PM3/5/12
to django-d...@googlegroups.com
On Tue, Mar 6, 2012 at 12:21, Martin Ostrovsky
<martin.o...@gmail.com> wrote:
> Danny reading your reply gave me an idea to try and it worked.
>
> I switched the order of the inlines. So I put C first, then B. This way C
> validates properly, then B is deleted and the cascaded deletion deletes C
> and everything works as expected.

Good to hear! (and a jquery one-liner can swap the way they are displayed)

And reading this thread gave me an idea of a slightly cleaner workaround:
- either define FK as nullable or provide a "sentinel" FK object for
collecting "deletables"
- set the FK .ondelete to SET_NULL or SET with a callable that assigns
the sentinel
- in the FK object's post_delete() - need to doublecheck if that gets
called last as well -, clean out all the objects referencing
None/sentinel

But it's still just a workaround. It appears to me like deleting
dependent objects first would avoid the problem altogether (can't
think of negative side effects).

Cheers,
Danny

Reply all
Reply to author
Forward
0 new messages