From 6befe6c733ae4a95a6065a444f16ff3346ee8233 Mon Sep 17 00:00:00 2001 From: Bert Constantin Date: Mon, 25 Oct 2010 09:28:08 +0200 Subject: [PATCH] added "queryset.get_real_instances()" usage, added testcase --- DOCS.rst | 31 +++++++++++++++++++------------ polymorphic/query.py | 21 ++++++++++++++++++--- polymorphic/tests.py | 16 +++++++++++++++- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/DOCS.rst b/DOCS.rst index e299610..b9cb203 100644 --- a/DOCS.rst +++ b/DOCS.rst @@ -235,16 +235,22 @@ existing polymorphic inheritance tree:: Non-Polymorphic Queries ----------------------- ->>> ModelA.objects.all().non_polymorphic() -. -[ , - , - ] +If you insert ``.non_polymorphic()`` anywhere into the query chain, then +django_polymorphic will simply leave out the final step of retrieving the +real objects, and the manager/queryset will return objects of the type of +the base class you used for the query, like vanilla Django would +(``ModelA`` in this example). + +There are no other changes in the behaviour of the queryset. For example, +enhancements for ``filter()`` or ``instance_of()`` etc. still work as expected. +If you do the final step yourself, you get the usual polymorphic result: + +>>> qs.get_real_instances() +[ , + , + ] + -Except for the return of the of the base class objects, there are no -changes in the behaviour of the queryset (i.e. the enhancements -for ``filter()`` or ``instance_of()`` etc. still work as expected). - About Queryset Methods ---------------------- @@ -268,10 +274,11 @@ About Queryset Methods (this case could be made to work, however it may be mostly unneeded).. The keyword-argument "polymorphic" is no longer supported. -+ ``get_real_instances(base_objects_list_or_queryset)`` allows you to turn a ++ ``get_real_instances()`` allows you to turn a queryset or list of base model objects efficiently into the real objects. - For example, you could do ``base_objects=ModelA.extra(...).non_polymorphic()`` - and then call ``real_objects=ModelA.objects.get_real_instances(base_objects)``. + For example, you could do ``base_objects_queryset=ModelA.extra(...).non_polymorphic()`` + and then call ``real_objects=base_objects_queryset.get_real_instances()``.Or alternatively + .``real_objects=ModelA.objects..get_real_instances(base_objects_queryset_or_object_list)`` * ``values()`` & ``values_list()`` currently do not return polymorphic results. This may change in the future however. If you want to use these diff --git a/polymorphic/query.py b/polymorphic/query.py index 5235608..b24de6a 100644 --- a/polymorphic/query.py +++ b/polymorphic/query.py @@ -91,13 +91,14 @@ class PolymorphicQuerySet(QuerySet): self.polymorphic_disabled = True return super(PolymorphicQuerySet, self).aggregate(*args, **kwargs) - # Since django_polymorphic 'V1.0 beta2', extra() always returns polymorphic results. + # Since django_polymorphic 'V1.0 beta2', extra() always returns polymorphic results.^ # The resulting objects are required to have a unique primary key within the result set # (otherwise an error is thrown). # The "polymorphic" keyword argument is not supported anymore. #def extra(self, *args, **kwargs): - def get_real_instances(self, base_result_objects): + + def _get_real_instances(self, base_result_objects): """ Polymorphic object loader @@ -229,7 +230,7 @@ class PolymorphicQuerySet(QuerySet): reached_end = True break - real_results = self.get_real_instances(base_result_objects) + real_results = self._get_real_instances(base_result_objects) for o in real_results: yield o @@ -243,3 +244,17 @@ class PolymorphicQuerySet(QuerySet): else: return super(PolymorphicQuerySet,self).__repr__(*args, **kwargs) + class _p_list_class(list): + def __repr__(self, *args, **kwargs): + result = [ repr(o) for o in self ] + return '[ ' + ',\n '.join(result) + ' ]' + + def get_real_instances(self, base_result_objects=None): + "same as _get_real_instances, but make sure that __repr__ for ShowField... creates correct output" + if not base_result_objects: base_result_objects=self + olist = self._get_real_instances(base_result_objects) + if not self.model.polymorphic_query_multiline_output: + return olist + clist=PolymorphicQuerySet._p_list_class(olist) + return clist + diff --git a/polymorphic/tests.py b/polymorphic/tests.py index 97ce12b..a97f0f5 100644 --- a/polymorphic/tests.py +++ b/polymorphic/tests.py @@ -285,7 +285,7 @@ __test__ = {"doctest": """ ] # manual get_real_instance() ->>> o=Model2A.base_objects.get(field1='C1') +>>> o=Model2A.objects.non_polymorphic().get(field1='C1') >>> o.get_real_instance() @@ -296,6 +296,20 @@ __test__ = {"doctest": """ , ] +# get_real_instances() +>>> qs.get_real_instances() +[ , + , + , + ] + +>>> l=list(qs) +>>> Model2A.objects.get_real_instances(l) +[ , + , + , + ] + ### test inheritance pointers & _base_managers