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 test
fix_request_path_info
Bert Constantin 2010-11-12 06:33:50 +01:00
parent ca329ff9b4
commit 4a4cfd82a2
7 changed files with 47 additions and 41 deletions

View File

@ -276,6 +276,9 @@ more simple and intuitive use:</p>
&gt;&gt;&gt; ModelA.objects.all() &gt;&gt;&gt; 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>

View File

@ -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

View File

@ -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 &quot;inner joins&quot; in these queries can perform very badly. The &quot;inner joins&quot; 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 &amp; Caveats</a></h1> <span id="restrictions"></span><h1><a class="toc-backref" href="#id8">Restrictions &amp; 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 &quot;Performance Problems&quot; above.</li> Please see &quot;Performance Problems&quot; 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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)