This looks exactly as I expect. Proxy models are not distinct in the
database from their parent models, they are just python wrappers around
them. It is documented and expected that creating instances of the parent
class creates instances of the proxy class. Since creating an instance of a
concrete subclass creates a parent model instance as well (you can see two
Generic instances when you print the Generic queryset) it should be no
surprise that you see two Specific instances -- they represent the same
data!

It is also expected behavior that you will never see Specific instances
unless you access the underlying data through Specific's manager.
InheritanceManager is doing a little magic to show you SpecificA instances,
but its behavior shouldn't be surprising. The Generic instance created by
SpecificA has a one-to-one join in the database giving it an unambiguous
representation as a SpecificA instance instead of Generic. Proxy models
don't have any representation at all in the database, so how is
InheritanceManager to know that Generic isn't the canonical representation?
As a thought experiment, consider if there were several different proxy
subclasses of Generic, how would you be able to choose which subclass to
show when there's no indication in the data?

I don't think anything strange is going on here, and the documentation is
adequate, though of course not perfect. Concrete subclasses create rows for
their parent class. Proxy classes represent the same data as their parent
class. Everything else follows naturally.

Best,
Alex Ogier
On Aug 18, 2013 12:32 AM, "Jorge C. Leitão" <[email protected]>
wrote:

> Hi there.
>
> I was working with proxies models and I found an odd behavior on a
> QuerySet, and I ask here whether it should be documented.
>
> Consider the following code:
>
> from django.db import models
>
> #from model_utils.managers import InheritanceManager
>
> class Generic(models.Model):
>     pass # comment this pass on second test
>     #objects = InheritanceManager()
>
> class Specific(Generic):
>     class Meta:
>         proxy = True
>
> class SpecificA(Generic):
>     pass
>
> Specific.objects.create()
> SpecificA.objects.create()
>
> print Generic.objects.all()
> print Specific.objects.all()
> print SpecificA.objects.all()
> #print Generic.objects.all().select_subclasses()
>
> Specific.objects.all().delete()
> SpecificA.objects.all().delete()
>
> The output is:
>
> [<Generic: Generic object>, <Generic: Generic object>]
> [<Specific: Specific object>, <Specific: Specific object>]
> [<SpecificA: SpecificA object>]
>
> Why there are two <Specific: Specific object> in the second list? I would
> expect 1 instance (the database has 2 rows in Generic and one 1 row in
> SpecificA).
>
> Furthermore, I also realized that the InheritanceManager (from
> django-model-utils<https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager>
> ) is doing something odd on proxy models, which could be due to the
> previous behavior. Uncommenting the three commented lines of the previous
> code and commenting pass, the fourth print gives
>
> [<Generic: Generic object>, <SpecificA: SpecificA object>]
>
> I would expect <Specific: Specific object> instead of <Generic: Generic
> object>.
>
> I tested this behavior in Django 1.5.2 and 1.6 and the results are
> equivalent.
>
> Can someone double check this and confirm that this behavior is odd?
>
> I searched in the documentation but I didn't found any reference that a
> Query on the proxy model returns instances subclasses of the parent model,
> instantiated as the proxy model itself. If this is the expected behavior,
> shouldn't we document it? Nevertheless, it seems to me difficult to assume
> that print Specific.objects.all()returns an instance created by
> SpecificA.objects.create().
>
> If this is not expected behavior, should I open a ticket with it?
>
>
> Cheers,
> Jorge
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/django-developers.
> For more options, visit https://groups.google.com/groups/opt_out.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to