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.
