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()
</pre>
</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>
</ul>

View File

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

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
returned from the database that were stored there, regardless how
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>
<li>Full support for ForeignKeys, ManyToManyFields and OneToToneFields</li>
<li>Filtering for classes, equivalent to python's isinstance():
@ -527,23 +527,17 @@ in the future).</li>
</div>
<div class="section" id="using-enhanced-q-objects-in-any-places">
<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
outside of polymorphic models/querysets. Example (using <tt class="docutils literal">limit_choices_to</tt>
to filter the selection of objects in the admin):</p>
<p>The queryset enhancements (e.g. <tt class="docutils literal">instance_of</tt>) 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:</p>
<pre class="literal-block">
class MyModel(models.Model):
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) ) )
normal_q_object = ModelA.translate_polymorphic_Q_object( Q(instance_of=Model2B) )
</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 class="section" id="nicely-displaying-polymorphic-querysets">
<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>
<div class="section" id="performance-problems-with-postgresql-mysql-and-sqlite3">
<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
ORM, if these use multi-table inheritance like Django's ORM does.
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">
<span id="restrictions"></span><h1><a class="toc-backref" href="#id8">Restrictions &amp; Caveats</a></h1>
<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>
<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">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,
but it would most likely make sense to have one.</li>
<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
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.

View File

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

View File

@ -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": """
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (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

View File

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