diff --git a/CHANGES.html b/CHANGES.html
index b008805..f7d0b15 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -276,6 +276,9 @@ more simple and intuitive use:
>>> ModelA.objects.all()
+added member function:
+normal_q_object = ModelA.translate_polymorphic_Q_object(enhanced_q_object)
+
misc changes/improvements
diff --git a/CHANGES.rst b/CHANGES.rst
index 2772f3a..b35344f 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -60,6 +60,9 @@ New Features and API changes in Beta 2 since Beta 1
>>> ModelA.objects.all()
+* added member function:
+ ``normal_q_object = ModelA.translate_polymorphic_Q_object(enhanced_q_object)``
+
* misc changes/improvements
Bugfixes
diff --git a/DOCS.html b/DOCS.html
index a8b886c..581f29e 100644
--- a/DOCS.html
+++ b/DOCS.html
@@ -310,7 +310,7 @@ output the ShowFieldType mixin has been used (
Fully automatic - generally makes sure that the same objects are
returned from the database that were stored there, regardless how
they are retrieved
-Only on models that request polymorphic behaviour however (and the
+Only on models that request polymorphic behaviour (and the
models inheriting from them)
Full support for ForeignKeys, ManyToManyFields and OneToToneFields
Filtering for classes, equivalent to python's isinstance():
@@ -527,23 +527,17 @@ in the future).
Using enhanced Q-objects in any Places
-
Sometimes it would be nice to be able to use the enhanced filter-definitions/Q-objects
-outside of polymorphic models/querysets. Example (using limit_choices_to
-to filter the selection of objects in the admin):
+
The queryset enhancements (e.g. instance_of) only work as arguments
+to the member functions of a polymorphic queryset. Occationally it may
+be useful to be able to use Q objects with these enhancements in other places.
+As Django doesn't understand these enhanced Q objects, you need to
+transform them manually into normal Q objects before you can feed them
+to a Django queryset or function:
-class MyModel(models.Model):
- somekey = model.ForeignKey(Model2A,
- limit_choices_to = Q(instance_of=Model2B) )
-
-
instance_of is a django_polymorphic-specific enhancement of Q objects, which the
-vanilla django function ForeignKey cannot process. In such cases you can do:
-
-from polymorphic import translate_polymorphic_Q_object
-
-class MyModel(models.Model):
- somekey = model.ForeignKey(Model2A,
- limit_choices_to = translate_polymorphic_Q_object( Model2A, Q(instance_of=Model2B) ) )
+normal_q_object = ModelA.translate_polymorphic_Q_object( Q(instance_of=Model2B) )
+
This function cannot be used at model creation time however (in models.py),
+as it may need to access the ContentTypes database table.
Nicely Displaying Polymorphic Querysets
@@ -677,7 +671,7 @@ SQL query for every object in the result which is not of class
Performance Problems with PostgreSQL, MySQL and SQLite3
-Current relational DBM systems seem to be have general problems with
+
Current relational DBM systems seem to have general problems with
the SQL queries produced by object relational mappers like the Django
ORM, if these use multi-table inheritance like Django's ORM does.
The "inner joins" in these queries can perform very badly.
@@ -690,12 +684,12 @@ multi table Model inheritance.
-- Database Performance regarding concrete Model inheritance in general
+
- Database Performance regarding concrete Model inheritance in general.
Please see "Performance Problems" above.
- Queryset methods values(), values_list(), select_related(),
defer() and only() are not yet fully supported (see above).
extra() has one restriction: the resulting objects are required to have
-a unique primary key within the result set
+a unique primary key within the result set.
- Django Admin Integration: There currently is no specific admin integration,
but it would most likely make sense to have one.
- Diamond shaped inheritance: There seems to be a general problem
diff --git a/DOCS.rst b/DOCS.rst
index 94e70a8..ded88dd 100644
--- a/DOCS.rst
+++ b/DOCS.rst
@@ -78,7 +78,7 @@ List of Features
* Fully automatic - generally makes sure that the same objects are
returned from the database that were stored there, regardless how
they are retrieved
-* Only on models that request polymorphic behaviour however (and the
+* Only on models that request polymorphic behaviour (and the
models inheriting from them)
* Full support for ForeignKeys, ManyToManyFields and OneToToneFields
* Filtering for classes, equivalent to python's isinstance():
@@ -319,22 +319,17 @@ About Queryset Methods
Using enhanced Q-objects in any Places
--------------------------------------
-Sometimes it would be nice to be able to use the enhanced filter-definitions/Q-objects
-outside of polymorphic models/querysets. Example (using ``limit_choices_to``
-to filter the selection of objects in the admin)::
+The queryset enhancements (e.g. ``instance_of``) only work as arguments
+to the member functions of a polymorphic queryset. Occationally it may
+be useful to be able to use Q objects with these enhancements in other places.
+As Django doesn't understand these enhanced Q objects, you need to
+transform them manually into normal Q objects before you can feed them
+to a Django queryset or function::
- class MyModel(models.Model):
- somekey = model.ForeignKey(Model2A,
- limit_choices_to = Q(instance_of=Model2B) )
+ normal_q_object = ModelA.translate_polymorphic_Q_object( Q(instance_of=Model2B) )
-``instance_of`` is a django_polymorphic-specific enhancement of Q objects, which the
-vanilla django function ``ForeignKey`` cannot process. In such cases you can do::
-
- from polymorphic import translate_polymorphic_Q_object
-
- class MyModel(models.Model):
- somekey = model.ForeignKey(Model2A,
- limit_choices_to = translate_polymorphic_Q_object( Model2A, Q(instance_of=Model2B) ) )
+This function cannot be used at model creation time however (in models.py),
+as it may need to access the ContentTypes database table.
Nicely Displaying Polymorphic Querysets
@@ -482,7 +477,7 @@ that it only needs one sql request per *object type*, and not *per object*.
Performance Problems with PostgreSQL, MySQL and SQLite3
-------------------------------------------------------
-Current relational DBM systems seem to be have general problems with
+Current relational DBM systems seem to have general problems with
the SQL queries produced by object relational mappers like the Django
ORM, if these use multi-table inheritance like Django's ORM does.
The "inner joins" in these queries can perform very badly.
@@ -501,13 +496,13 @@ Please also see this `post (and comments) from Jacob Kaplan-Moss`_.
Restrictions & Caveats
======================
-* Database Performance regarding concrete Model inheritance in general
+* Database Performance regarding concrete Model inheritance in general.
Please see "Performance Problems" above.
* Queryset methods ``values()``, ``values_list()``, ``select_related()``,
``defer()`` and ``only()`` are not yet fully supported (see above).
``extra()`` has one restriction: the resulting objects are required to have
- a unique primary key within the result set
+ a unique primary key within the result set.
* Django Admin Integration: There currently is no specific admin integration,
but it would most likely make sense to have one.
diff --git a/polymorphic/polymorphic_model.py b/polymorphic/polymorphic_model.py
index c9acd30..99adf45 100644
--- a/polymorphic/polymorphic_model.py
+++ b/polymorphic/polymorphic_model.py
@@ -27,6 +27,7 @@ from base import PolymorphicModelBase
from manager import PolymorphicManager
from query import PolymorphicQuerySet
from showfields import ShowFieldType
+from query_translate import translate_polymorphic_Q_object
###################################################################################
@@ -76,6 +77,10 @@ class PolymorphicModel(models.Model):
objects = PolymorphicManager()
base_objects = models.Manager()
+ @classmethod
+ def translate_polymorphic_Q_object(self_class,q):
+ return translate_polymorphic_Q_object(self_class,q)
+
def pre_save_polymorphic(self):
"""Normally not needed.
This function may be called manually in special use-cases. When the object
diff --git a/polymorphic/tests.py b/polymorphic/tests.py
index 64f5105..4984968 100644
--- a/polymorphic/tests.py
+++ b/polymorphic/tests.py
@@ -141,7 +141,7 @@ class BlogEntry(ShowFieldTypeAndContent, PolymorphicModel):
text = models.CharField(max_length=10)
class BlogEntry_limit_choices_to(ShowFieldTypeAndContent, PolymorphicModel):
- blog = models.ForeignKey(BlogBase, limit_choices_to=translate_polymorphic_Q_object(BlogBase, Q(instance_of=BlogA) ) )
+ blog = models.ForeignKey(BlogBase)
text = models.CharField(max_length=10)
class ModelFieldNameTest(ShowFieldType, PolymorphicModel):
@@ -159,7 +159,7 @@ class InitTestModelSubclass(InitTestModel):
# UUID tests won't work with Django 1.1
if not (django_VERSION[0] <= 1 and django_VERSION[1] <= 1):
- try: from polymorphic.test_tools import UUIDField
+ try: from polymorphic.tools_for_tests import UUIDField
except: pass
if 'UUIDField' in globals():
import uuid
@@ -369,6 +369,12 @@ __test__ = {"doctest": """
,
]
+# translate_polymorphic_Q_object
+>>> q=Model2A.translate_polymorphic_Q_object( Q(instance_of=Model2C) )
+>>> Model2A.objects.filter(q)
+[ ,
+ ]
+
### test inheritance pointers & _base_managers
diff --git a/polymorphic/test_tools.py b/polymorphic/tools_for_tests.py
similarity index 98%
rename from polymorphic/test_tools.py
rename to polymorphic/tools_for_tests.py
index 3bdb639..3d93201 100644
--- a/polymorphic/test_tools.py
+++ b/polymorphic/tools_for_tests.py
@@ -82,7 +82,7 @@ class UUIDField(models.CharField):
else:
raise UUIDVersionError("UUID version %s is not valid." % self.version)
- def db_type(self):
+ def db_type(self, connection):
from django.conf import settings
return UUIDField._CREATE_COLUMN_TYPES.get(settings.DATABASE_ENGINE, "char(%s)" % self.max_length)
@@ -122,7 +122,7 @@ class UUIDField(models.CharField):
setattr(model_instance, self.attname, value)
return value
- def get_db_prep_value(self, value):
+ def get_db_prep_value(self, value, connection, prepared):
"""Casts uuid.UUID values into the format expected by the back end for use in queries"""
if isinstance(value, uuid.UUID):
return smart_unicode(value)