From 2c47db8fcc284a92d2c9769ba503603fbea92660 Mon Sep 17 00:00:00 2001 From: Bert Constantin Date: Mon, 24 Jan 2011 16:37:38 +0100 Subject: [PATCH] Fixed github issue 15 (query result incomplete with inheritance). Thanks to John Debs. --- CHANGES.html | 33 ++++++++++++++++++++++----------- CHANGES.rst | 12 ++++++++++++ polymorphic/base.py | 7 +++++++ polymorphic/query.py | 6 ++++-- polymorphic/tests.py | 22 ++++++++++++++++++++++ 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/CHANGES.html b/CHANGES.html index f7d0b15..9eaf216 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -225,6 +225,17 @@ ul.auto-toc {

Changelog

+
+

2011-01-24 V1.0 Release Candidate 1

+
+

Bugfixes

+
    +
  • Fixed GitHub issue 15 (query result incomplete with inheritance). +Thanks to John Debs for reporting and the test case.
  • +
+
+
+

2010-11-11 V1.0 Beta 2

@@ -283,7 +294,7 @@ more simple and intuitive use:

-
+

Bugfixes

  • Custom fields could cause problems when used as the primary key. @@ -349,7 +360,7 @@ transform the result to its polymorphic equivalent.

-
+

Bugfixes

  • Removed requirement for primary key to be an IntegerField. @@ -387,7 +398,7 @@ just python manage.py test.


-
+

2010-2-22

IMPORTANT: API Changed (import path changed), and Installation Note

The django_polymorphic source code has been restructured @@ -411,11 +422,11 @@ from polymorphic.models import PolymorphicModel, ...

  • minor API addition: 'from polymorphic import VERSION, get_version'
-
+

New Features

Python 2.4 compatibility, contributed by Charles Leifer. Thanks!

-
+

Bugfixes

Fix: The exception "...has no attribute 'sub_and_superclass_dict'" could be raised. (This occurred if a subclass defined __init__ @@ -429,7 +440,7 @@ Now it is possible to give a field the same name as the class


-
+

2010-2-4

New features (and documentation)

@@ -442,7 +453,7 @@ only() allowed (but not yet supported)

More about these additions in the docs: http://bserve.webhop.org/wiki/django_polymorphic/doc

-
+

Bugfixes

  • fix remaining potential accessor name clashes (but this only works @@ -467,7 +478,7 @@ support for natural keys in serialization).

-
+

2010-1-30

Fixed ContentType related field accessor clash (an error emitted by model validation) by adding related_name to the ContentType @@ -475,7 +486,7 @@ ForeignKey. This happened if your polymorphc model used a ContentType ForeignKey. Thanks to Andrew Ingram.


-
+

2010-1-29

Restructured django_polymorphic into a regular Django add-on application. This is needed for the management commands, and @@ -486,7 +497,7 @@ as well (and it makes sure the tests are always included).

("installation/testing") for more info.


-
+

2010-1-28

Added the polymorphic_dumpdata management command (github issue 4), for creating fixtures, this should be used instead of @@ -497,7 +508,7 @@ needs Django 1.2 (important as any polymorphic model uses ContentType).


-
+

2010-1-26

IMPORTANT - database schema change (more info in change log). I hope I got this change in early enough before anyone started diff --git a/CHANGES.rst b/CHANGES.rst index b35344f..da94d0d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,6 +3,18 @@ Changelog ++++++++++ +2011-01-24 V1.0 Release Candidate 1 +=================================== + +Bugfixes +------------------------ + +* Fixed GitHub issue 15 (query result incomplete with inheritance). + Thanks to John Debs for reporting and the test case. + + +------------------------------------------------------------------ + 2010-11-11 V1.0 Beta 2 ====================== diff --git a/polymorphic/base.py b/polymorphic/base.py index f49306a..0e56199 100644 --- a/polymorphic/base.py +++ b/polymorphic/base.py @@ -76,6 +76,13 @@ class PolymorphicModelBase(ModelBase): # for __init__ function of this class (monkeypatching inheritance accessors) new_class.polymorphic_super_sub_accessors_replaced = False + # determine the name of the primary key field and store it into the class variable + # polymorphic_primary_key_name (it is needed by query.py) + for f in new_class._meta.fields: + if f.primary_key and type(f)!=models.OneToOneField: + new_class.polymorphic_primary_key_name=f.name + break + return new_class def get_inherited_managers(self, attrs): diff --git a/polymorphic/query.py b/polymorphic/query.py index 1bb8b16..6f059dc 100644 --- a/polymorphic/query.py +++ b/polymorphic/query.py @@ -161,7 +161,9 @@ class PolymorphicQuerySet(QuerySet): # We get different type(o.pk) in this case. # We work around this by using the real name of the field directly # for accessing the primary key of the the derived objects. - pk_name = self.model._meta.pk.name + # We might assume that self.model._meta.pk.name gives us the name of the primary key field, + # but it doesn't. Therefore we use polymorphic_primary_key_name, which we set up in base.py. + pk_name = self.model.polymorphic_primary_key_name # For each model in "idlist_per_model" request its objects (the real model) # from the db and store them in results[]. @@ -184,7 +186,7 @@ class PolymorphicQuerySet(QuerySet): for select_field_name in self.query.extra_select.keys(): attr = getattr(base_result_objects_by_id[o_pk], select_field_name) setattr(o, select_field_name, attr) - + results[o_pk] = o # re-create correct order and return result list diff --git a/polymorphic/tests.py b/polymorphic/tests.py index 4984968..7005799 100644 --- a/polymorphic/tests.py +++ b/polymorphic/tests.py @@ -156,6 +156,14 @@ class InitTestModelSubclass(InitTestModel): def x(self): return 'XYZ' +# models from github issue +class Top(PolymorphicModel): + name = models.CharField(max_length=50) +class Middle(Top): + description = models.TextField() +class Bottom(Middle): + author = models.CharField(max_length=50) + # UUID tests won't work with Django 1.1 if not (django_VERSION[0] <= 1 and django_VERSION[1] <= 1): @@ -610,6 +618,20 @@ __test__ = {"doctest": """ #>>> print 'DiamondXY fields 1: field_b "%s", field_x "%s", field_y "%s"' % (o.field_b, o.field_x, o.field_y) #DiamondXY fields 1: field_b "a", field_x "x", field_y "y" +# test for github issue +>>> t = Top() +>>> t.save() +>>> m = Middle() +>>> m.save() +>>> b = Bottom() +>>> b.save() +>>> Top.objects.all() +[, , ] +>>> Middle.objects.all() +[, ] +>>> Bottom.objects.all() +[] + >>> settings.DEBUG=False