﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
18094	`pre_delete` and `post_delete` signals are not correctly sent in inheritance scenarios involving proxy models	Simon Charette	Simon Charette	"This is a follow up of #18083.

Given the following models and signals (as of r17887):

{{{#!python

from django.db import models
from django.db.models import signals


class A(models.Model):
    pass

class AProxy(A):
    class Meta:
        proxy = True

class B(A):
    pass

class BFirstProxy(B):
    class Meta:
        proxy = True

class BSecondProxy(B):
    class Meta:
        proxy = True

class BFirstProxyFirstProxy(BFirstProxy):
    class Meta:
        proxy = True

class BFirstProxySecondProxy(BFirstProxy):
    class Meta:
        proxy = True


def pre_delete(sender, instance, **kwargs):
    print ""`pre_delete` %r %r"" % (sender, instance)

signals.pre_delete.connect(pre_delete, A)
signals.pre_delete.connect(pre_delete, AProxy)
signals.pre_delete.connect(pre_delete, B)
signals.pre_delete.connect(pre_delete, BFirstProxy)
signals.pre_delete.connect(pre_delete, BSecondProxy)
signals.pre_delete.connect(pre_delete, BFirstProxyFirstProxy)
signals.pre_delete.connect(pre_delete, BFirstProxySecondProxy)

def post_delete(sender, instance, **kwargs):
    return # Avoid dispatching for output clarity
    print ""`post_delete` %r %r"" % (sender, instance)

signals.post_delete.connect(post_delete, A)
signals.post_delete.connect(post_delete, AProxy)
signals.post_delete.connect(post_delete, B)
signals.post_delete.connect(post_delete, BFirstProxy)
signals.post_delete.connect(post_delete, BSecondProxy)
signals.post_delete.connect(post_delete, BFirstProxyFirstProxy)
signals.post_delete.connect(post_delete, BFirstProxySecondProxy)
}}}

`pre_delete` and `post_delete` signals dispatching depends on the deletion source and don't propagate up the proxy chain nor to the proxy leaves. i.e. (here `post_delete`'s dispatching should behave the same)

== Basic model proxy ==
'''Actual behaviours'''
{{{
>>> A.objects.create().delete()
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
>>> AProxy.objects.create().delete()
`pre_delete` <class 'proxy_signals.models.AProxy'> <AProxy: AProxy object>
}}}

'''Expected behaviour in both cases'''
{{{
`pre_delete` <class 'proxy_signals.models.AProxy'> <AProxy: AProxy object>
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
}}}

== Multi-table inheritance model proxy ==
'''Actual behaviours'''
{{{
>>> B.objects.create().delete()
`pre_delete` <class 'proxy_signals.models.B'> <B: B object>
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
>>> BFirstProxy.objects.create().delete()
`pre_delete` <class 'proxy_signals.models.BFirstProxy'> <BFirstProxy: BFirstProxy object>
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
>>> BSecondProxy.objects.create().delete()
`pre_delete` <class 'proxy_signals.models.BSecondProxy'> <BSecondProxy: BSecondProxy object>
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
>>> BFirstProxyFirstProxy.objects.create().delete()
`pre_delete` <class 'proxy_signals.models.BFirstProxyFirstProxy'> <BFirstProxyFirstProxy: BFirstProxyFirstProxy object>
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
>>> BFirstProxySecondProxy.objects.create().delete()
`pre_delete` <class 'proxy_signals.models.BFirstProxySecondProxy'> <BFirstProxySecondProxy: BFirstProxySecondProxy object>
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
}}}

'''Expected behaviour in all cases'''
{{{
`pre_delete` <class 'proxy_signals.models.BFirstProxyFirstProxy'> <BFirstProxyFirstProxy: BFirstProxyFirstProxy object>
`pre_delete` <class 'proxy_signals.models.BFirstProxySecondProxy'> <BFirstProxySecondProxy: BFirstProxySecondProxy object>
`pre_delete` <class 'proxy_signals.models.BFirstProxy'> <BFirstProxy: BFirstProxy object>
`pre_delete` <class 'proxy_signals.models.BSecondProxy'> <BSecondProxy: BSecondProxy object>
`pre_delete` <class 'proxy_signals.models.B'> <B: B object>
`pre_delete` <class 'proxy_signals.models.AProxy'> <AProxy: AProxy object>
`pre_delete` <class 'proxy_signals.models.A'> <A: A object>
}}}

What needs to be fixed:
* Dispatch the `concrete_model` signals even when the source is an instance of a proxy
* Dispatch the signals for all proxy of concrete models involved in the deletion
* Preserve the expected dispatching order

Failing integrated TestCase to come.
"	Bug	closed	Database layer (models, ORM)	1.4	Normal	duplicate	model proxy multi-table inheritance signals delete	Chris Streeter	Unreviewed	0	0	0	0	0	0
