translate_polymorphic_Q_object: fixed test case, and made the function a member of PolymorphicObject.
Minor test fixes: warnings fixed, test_tool.py renamed as it's no testfix_request_path_info
parent
ca329ff9b4
commit
4a4cfd82a2
|
|
@ -276,6 +276,9 @@ more simple and intuitive use:</p>
|
||||||
>>> ModelA.objects.all()
|
>>> ModelA.objects.all()
|
||||||
</pre>
|
</pre>
|
||||||
</li>
|
</li>
|
||||||
|
<li><p class="first">added member function:
|
||||||
|
<tt class="docutils literal">normal_q_object = ModelA.translate_polymorphic_Q_object(enhanced_q_object)</tt></p>
|
||||||
|
</li>
|
||||||
<li><p class="first">misc changes/improvements</p>
|
<li><p class="first">misc changes/improvements</p>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,9 @@ New Features and API changes in Beta 2 since Beta 1
|
||||||
|
|
||||||
>>> ModelA.objects.all()
|
>>> ModelA.objects.all()
|
||||||
|
|
||||||
|
* added member function:
|
||||||
|
``normal_q_object = ModelA.translate_polymorphic_Q_object(enhanced_q_object)``
|
||||||
|
|
||||||
* misc changes/improvements
|
* misc changes/improvements
|
||||||
|
|
||||||
Bugfixes
|
Bugfixes
|
||||||
|
|
|
||||||
32
DOCS.html
32
DOCS.html
|
|
@ -310,7 +310,7 @@ output the <tt class="docutils literal">ShowFieldType</tt> mixin has been used (
|
||||||
<li>Fully automatic - generally makes sure that the same objects are
|
<li>Fully automatic - generally makes sure that the same objects are
|
||||||
returned from the database that were stored there, regardless how
|
returned from the database that were stored there, regardless how
|
||||||
they are retrieved</li>
|
they are retrieved</li>
|
||||||
<li>Only on models that request polymorphic behaviour however (and the
|
<li>Only on models that request polymorphic behaviour (and the
|
||||||
models inheriting from them)</li>
|
models inheriting from them)</li>
|
||||||
<li>Full support for ForeignKeys, ManyToManyFields and OneToToneFields</li>
|
<li>Full support for ForeignKeys, ManyToManyFields and OneToToneFields</li>
|
||||||
<li>Filtering for classes, equivalent to python's isinstance():
|
<li>Filtering for classes, equivalent to python's isinstance():
|
||||||
|
|
@ -527,23 +527,17 @@ in the future).</li>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="using-enhanced-q-objects-in-any-places">
|
<div class="section" id="using-enhanced-q-objects-in-any-places">
|
||||||
<h2>Using enhanced Q-objects in any Places</h2>
|
<h2>Using enhanced Q-objects in any Places</h2>
|
||||||
<p>Sometimes it would be nice to be able to use the enhanced filter-definitions/Q-objects
|
<p>The queryset enhancements (e.g. <tt class="docutils literal">instance_of</tt>) only work as arguments
|
||||||
outside of polymorphic models/querysets. Example (using <tt class="docutils literal">limit_choices_to</tt>
|
to the member functions of a polymorphic queryset. Occationally it may
|
||||||
to filter the selection of objects in the admin):</p>
|
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:</p>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
class MyModel(models.Model):
|
normal_q_object = ModelA.translate_polymorphic_Q_object( Q(instance_of=Model2B) )
|
||||||
somekey = model.ForeignKey(Model2A,
|
|
||||||
limit_choices_to = Q(instance_of=Model2B) )
|
|
||||||
</pre>
|
|
||||||
<p><tt class="docutils literal">instance_of</tt> is a django_polymorphic-specific enhancement of Q objects, which the
|
|
||||||
vanilla django function <tt class="docutils literal">ForeignKey</tt> cannot process. In such cases you can do:</p>
|
|
||||||
<pre class="literal-block">
|
|
||||||
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) ) )
|
|
||||||
</pre>
|
</pre>
|
||||||
|
<p>This function cannot be used at model creation time however (in models.py),
|
||||||
|
as it may need to access the ContentTypes database table.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="nicely-displaying-polymorphic-querysets">
|
<div class="section" id="nicely-displaying-polymorphic-querysets">
|
||||||
<h2>Nicely Displaying Polymorphic Querysets</h2>
|
<h2>Nicely Displaying Polymorphic Querysets</h2>
|
||||||
|
|
@ -677,7 +671,7 @@ SQL query for every object in the result which is not of class <tt class="docuti
|
||||||
that it only needs one sql request per <em>object type</em>, and not <em>per object</em>.</p>
|
that it only needs one sql request per <em>object type</em>, and not <em>per object</em>.</p>
|
||||||
<div class="section" id="performance-problems-with-postgresql-mysql-and-sqlite3">
|
<div class="section" id="performance-problems-with-postgresql-mysql-and-sqlite3">
|
||||||
<span id="performance"></span><h2>Performance Problems with PostgreSQL, MySQL and SQLite3</h2>
|
<span id="performance"></span><h2>Performance Problems with PostgreSQL, MySQL and SQLite3</h2>
|
||||||
<p>Current relational DBM systems seem to be have general problems with
|
<p>Current relational DBM systems seem to have general problems with
|
||||||
the SQL queries produced by object relational mappers like the Django
|
the SQL queries produced by object relational mappers like the Django
|
||||||
ORM, if these use multi-table inheritance like Django's ORM does.
|
ORM, if these use multi-table inheritance like Django's ORM does.
|
||||||
The "inner joins" in these queries can perform very badly.
|
The "inner joins" in these queries can perform very badly.
|
||||||
|
|
@ -690,12 +684,12 @@ multi table Model inheritance.</p>
|
||||||
<div class="section" id="restrictions-caveats">
|
<div class="section" id="restrictions-caveats">
|
||||||
<span id="restrictions"></span><h1><a class="toc-backref" href="#id8">Restrictions & Caveats</a></h1>
|
<span id="restrictions"></span><h1><a class="toc-backref" href="#id8">Restrictions & Caveats</a></h1>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Database Performance regarding concrete Model inheritance in general
|
<li>Database Performance regarding concrete Model inheritance in general.
|
||||||
Please see "Performance Problems" above.</li>
|
Please see "Performance Problems" above.</li>
|
||||||
<li>Queryset methods <tt class="docutils literal">values()</tt>, <tt class="docutils literal">values_list()</tt>, <tt class="docutils literal">select_related()</tt>,
|
<li>Queryset methods <tt class="docutils literal">values()</tt>, <tt class="docutils literal">values_list()</tt>, <tt class="docutils literal">select_related()</tt>,
|
||||||
<tt class="docutils literal">defer()</tt> and <tt class="docutils literal">only()</tt> are not yet fully supported (see above).
|
<tt class="docutils literal">defer()</tt> and <tt class="docutils literal">only()</tt> are not yet fully supported (see above).
|
||||||
<tt class="docutils literal">extra()</tt> has one restriction: the resulting objects are required to have
|
<tt class="docutils literal">extra()</tt> has one restriction: the resulting objects are required to have
|
||||||
a unique primary key within the result set</li>
|
a unique primary key within the result set.</li>
|
||||||
<li>Django Admin Integration: There currently is no specific admin integration,
|
<li>Django Admin Integration: There currently is no specific admin integration,
|
||||||
but it would most likely make sense to have one.</li>
|
but it would most likely make sense to have one.</li>
|
||||||
<li>Diamond shaped inheritance: There seems to be a general problem
|
<li>Diamond shaped inheritance: There seems to be a general problem
|
||||||
|
|
|
||||||
31
DOCS.rst
31
DOCS.rst
|
|
@ -78,7 +78,7 @@ List of Features
|
||||||
* Fully automatic - generally makes sure that the same objects are
|
* Fully automatic - generally makes sure that the same objects are
|
||||||
returned from the database that were stored there, regardless how
|
returned from the database that were stored there, regardless how
|
||||||
they are retrieved
|
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)
|
models inheriting from them)
|
||||||
* Full support for ForeignKeys, ManyToManyFields and OneToToneFields
|
* Full support for ForeignKeys, ManyToManyFields and OneToToneFields
|
||||||
* Filtering for classes, equivalent to python's isinstance():
|
* Filtering for classes, equivalent to python's isinstance():
|
||||||
|
|
@ -319,22 +319,17 @@ About Queryset Methods
|
||||||
Using enhanced Q-objects in any Places
|
Using enhanced Q-objects in any Places
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
Sometimes it would be nice to be able to use the enhanced filter-definitions/Q-objects
|
The queryset enhancements (e.g. ``instance_of``) only work as arguments
|
||||||
outside of polymorphic models/querysets. Example (using ``limit_choices_to``
|
to the member functions of a polymorphic queryset. Occationally it may
|
||||||
to filter the selection of objects in the admin)::
|
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):
|
normal_q_object = ModelA.translate_polymorphic_Q_object( Q(instance_of=Model2B) )
|
||||||
somekey = model.ForeignKey(Model2A,
|
|
||||||
limit_choices_to = Q(instance_of=Model2B) )
|
|
||||||
|
|
||||||
``instance_of`` is a django_polymorphic-specific enhancement of Q objects, which the
|
This function cannot be used at model creation time however (in models.py),
|
||||||
vanilla django function ``ForeignKey`` cannot process. In such cases you can do::
|
as it may need to access the ContentTypes database table.
|
||||||
|
|
||||||
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) ) )
|
|
||||||
|
|
||||||
|
|
||||||
Nicely Displaying Polymorphic Querysets
|
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
|
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
|
the SQL queries produced by object relational mappers like the Django
|
||||||
ORM, if these use multi-table inheritance like Django's ORM does.
|
ORM, if these use multi-table inheritance like Django's ORM does.
|
||||||
The "inner joins" in these queries can perform very badly.
|
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
|
Restrictions & Caveats
|
||||||
======================
|
======================
|
||||||
|
|
||||||
* Database Performance regarding concrete Model inheritance in general
|
* Database Performance regarding concrete Model inheritance in general.
|
||||||
Please see "Performance Problems" above.
|
Please see "Performance Problems" above.
|
||||||
|
|
||||||
* Queryset methods ``values()``, ``values_list()``, ``select_related()``,
|
* Queryset methods ``values()``, ``values_list()``, ``select_related()``,
|
||||||
``defer()`` and ``only()`` are not yet fully supported (see above).
|
``defer()`` and ``only()`` are not yet fully supported (see above).
|
||||||
``extra()`` has one restriction: the resulting objects are required to have
|
``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,
|
* Django Admin Integration: There currently is no specific admin integration,
|
||||||
but it would most likely make sense to have one.
|
but it would most likely make sense to have one.
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ from base import PolymorphicModelBase
|
||||||
from manager import PolymorphicManager
|
from manager import PolymorphicManager
|
||||||
from query import PolymorphicQuerySet
|
from query import PolymorphicQuerySet
|
||||||
from showfields import ShowFieldType
|
from showfields import ShowFieldType
|
||||||
|
from query_translate import translate_polymorphic_Q_object
|
||||||
|
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
|
|
@ -76,6 +77,10 @@ class PolymorphicModel(models.Model):
|
||||||
objects = PolymorphicManager()
|
objects = PolymorphicManager()
|
||||||
base_objects = models.Manager()
|
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):
|
def pre_save_polymorphic(self):
|
||||||
"""Normally not needed.
|
"""Normally not needed.
|
||||||
This function may be called manually in special use-cases. When the object
|
This function may be called manually in special use-cases. When the object
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ class BlogEntry(ShowFieldTypeAndContent, PolymorphicModel):
|
||||||
text = models.CharField(max_length=10)
|
text = models.CharField(max_length=10)
|
||||||
|
|
||||||
class BlogEntry_limit_choices_to(ShowFieldTypeAndContent, PolymorphicModel):
|
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)
|
text = models.CharField(max_length=10)
|
||||||
|
|
||||||
class ModelFieldNameTest(ShowFieldType, PolymorphicModel):
|
class ModelFieldNameTest(ShowFieldType, PolymorphicModel):
|
||||||
|
|
@ -159,7 +159,7 @@ class InitTestModelSubclass(InitTestModel):
|
||||||
|
|
||||||
# UUID tests won't work with Django 1.1
|
# UUID tests won't work with Django 1.1
|
||||||
if not (django_VERSION[0] <= 1 and django_VERSION[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
|
except: pass
|
||||||
if 'UUIDField' in globals():
|
if 'UUIDField' in globals():
|
||||||
import uuid
|
import uuid
|
||||||
|
|
@ -369,6 +369,12 @@ __test__ = {"doctest": """
|
||||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
||||||
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
||||||
|
|
||||||
|
# translate_polymorphic_Q_object
|
||||||
|
>>> q=Model2A.translate_polymorphic_Q_object( Q(instance_of=Model2C) )
|
||||||
|
>>> Model2A.objects.filter(q)
|
||||||
|
[ <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
|
||||||
|
<Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
|
||||||
|
|
||||||
|
|
||||||
### test inheritance pointers & _base_managers
|
### test inheritance pointers & _base_managers
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ class UUIDField(models.CharField):
|
||||||
else:
|
else:
|
||||||
raise UUIDVersionError("UUID version %s is not valid." % self.version)
|
raise UUIDVersionError("UUID version %s is not valid." % self.version)
|
||||||
|
|
||||||
def db_type(self):
|
def db_type(self, connection):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
return UUIDField._CREATE_COLUMN_TYPES.get(settings.DATABASE_ENGINE, "char(%s)" % self.max_length)
|
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)
|
setattr(model_instance, self.attname, value)
|
||||||
return 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"""
|
"""Casts uuid.UUID values into the format expected by the back end for use in queries"""
|
||||||
if isinstance(value, uuid.UUID):
|
if isinstance(value, uuid.UUID):
|
||||||
return smart_unicode(value)
|
return smart_unicode(value)
|
||||||
Loading…
Reference in New Issue