Started cleaning up

Now that the line was drawn, it's time for cleanups and improvements.
fix_request_path_info
Christopher Glass 2011-12-20 18:51:05 +00:00
parent 60813621a1
commit ce97087f78
3 changed files with 0 additions and 1691 deletions

View File

@ -1,524 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title></title>
<style type="text/css">
h1, h2, h3, h4,
#table-of-contents
{
color: #47c;
}
h1 { padding-top: 15px; }
h2 { padding-top: 10px; }
h3 { padding-top: 7px; }
a:hover { border-bottom: 1px solid #0066cc; }
a {color: #0066cc; text-decoration: none;}
li {
padding-top: 5px;
padding-bottom: 5px;
}
tt {
color: #080;
}
blockquote tt {
color: #000
}
.first {
margin-top: 0 }
.last {
margin-bottom: 0 }
/*
a.toc-backref {
text-decoration: none ;
color: black }
*/
dd {
margin-bottom: 0.5em }
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em }
div.footer, div.header {
font-size: smaller }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr {
width: 75% }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.line-block {
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option-argument {
font-style: italic }
span.pre {
white-space: pre }
span.problematic {
color: red }
table {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.citation {
border-left: solid thin gray ;
padding-left: 0.5ex }
table.docinfo {
margin: 2em 4em }
table.footnote {
border-left: solid thin black ;
padding-left: 0.5ex }
td, th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
th.docinfo-name, th.field-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap }
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
font-size: 100% }
tt, pre.literal-block, pre.doctest-block {
font-size: 115%;
line-height: 150% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<div class="section" id="django-polymorphic">
<h1><em>django_polymorphic</em></h1>
</div>
<div class="section" id="changelog">
<h1>Changelog</h1>
<div class="section" id="v1-0-release-candidate-1">
<h2>2011-01-24 V1.0 Release Candidate 1</h2>
<div class="section" id="bugfixes">
<h3>Bugfixes</h3>
<ul class="simple">
<li>Fixed GitHub issue 15 (query result incomplete with inheritance).
Thanks to John Debs for reporting and the test case.</li>
</ul>
</div>
</div>
<hr class="docutils" />
<div class="section" id="v1-0-beta-2">
<h2>2010-11-11 V1.0 Beta 2</h2>
<div class="section" id="this-is-a-v1-0-testing-release">
<h3>This is a V1.0 Testing Release</h3>
<p>Beta 2 accumulated somewhat more changes than intended, and also
has been delayed by DBMS benchmark testing I wanted to do on model
inheritance. These benchmarks show that there are considerable
problems with concrete model inheritance and contemporary DBM systems.
The results will be forthcoming on the google discussion forum.</p>
<p>Please also see:
<a class="reference external" href="http://www.jacobian.org/writing/concrete-inheritance/">http://www.jacobian.org/writing/concrete-inheritance/</a></p>
<p>The API should be stable now with Beta 2, so it's just about potential
bugfixes from now on regarding V1.0.</p>
<p>Beta 2 is still intended for testing and development environments and not
for production. No complaints have been heard regarding Beta 1 however,
and Beta 1 is used on a few production sites by some enterprising users.</p>
<p>There will be a release candidate for V1.0 in the very near future.</p>
</div>
<div class="section" id="new-features-and-api-changes-in-beta-2-since-beta-1">
<h3>New Features and API changes in Beta 2 since Beta 1</h3>
<ul>
<li><p class="first">API CHANGE: <tt class="docutils literal">.extra()</tt> has been re-implemented. Now it's polymorphic by
default and works (nearly) without restrictions (please see docs). This is a (very)
incompatible API change regarding previous versions of django_polymorphic.
Support for the <tt class="docutils literal">polymorphic</tt> keyword parameter has been removed.
You can get back the non-polymorphic behaviour by using
<tt class="docutils literal"><span class="pre">ModelA.objects.non_polymorphic().extra(...)</span></tt>.</p>
</li>
<li><p class="first">API CHANGE: <tt class="docutils literal">ShowFieldContent</tt> and <tt class="docutils literal">ShowFieldTypeAndContent</tt> now
use a slightly different output format. If this causes too much trouble for
your test cases, you can get the old behaviour back (mostly) by adding
<tt class="docutils literal">polymorphic_showfield_old_format = True</tt> to your model definitions.
<tt class="docutils literal"><span class="pre">ShowField...</span></tt> now also produces more informative output for custom
primary keys.</p>
</li>
<li><p class="first"><tt class="docutils literal">.non_polymorphic()</tt> queryset member function added. This is preferable to
using <tt class="docutils literal"><span class="pre">.base_objects...</span></tt>, as it just makes the resulting queryset non-polymorphic
and does not change anything else in the behaviour of the manager used (while
<tt class="docutils literal">.base_objects</tt> is just a different manager).</p>
</li>
<li><p class="first"><tt class="docutils literal">.get_real_instances()</tt>: implementation modified to allow the following
more simple and intuitive use:</p>
<pre class="literal-block">
&gt;&gt;&gt; qs = ModelA.objects.all().non_polymorphic()
&gt;&gt;&gt; qs.get_real_instances()
</pre>
<p>which is equivalent to:</p>
<pre class="literal-block">
&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>
</div>
<div class="section" id="id1">
<h3>Bugfixes</h3>
<ul class="simple">
<li>Custom fields could cause problems when used as the primary key.
In derived models, Django's automatic &quot;.pk&quot; field does not always work
correctly for such custom fields: &quot;some_object.pk&quot; and &quot;some_object.id&quot;
return different results (which they shouldn't, as pk should always be just
an alias for the primary key field). It's unclear yet if the problem lies in
Django or the affected custom fields. Regardless, the problem resulting
from this has been fixed with a small workaround.
&quot;python manage.py test polymorphic&quot; also tests and reports on this problem now.
Thanks to Mathieu Steele for reporting and the test case.</li>
</ul>
</div>
</div>
<hr class="docutils" />
<div class="section" id="v1-0-beta-1">
<h2>2010-10-18 V1.0 Beta 1</h2>
<div class="section" id="this-is-a-v1-0-beta-testing-release">
<h3>This is a V1.0 Beta/Testing Release</h3>
<p>This release is mostly a cleanup and maintenance release that also
improves a number of minor things and fixes one (non-critical) bug.</p>
<p>Some pending API changes and corrections have been folded into this release
in order to make the upcoming V1.0 API as stable as possible.</p>
<p>This release is also about getting feedback from you in case you don't
approve of any of these changes or would like to get additional
API fixes into V1.0.</p>
<p>The release contains a considerable amount of changes in some of the more
critical parts of the software. It's intended for testing and development
environments and not for production environments. For these, it's best to
wait a few weeks for the proper V1.0 release, to allow some time for any
potential problems to show up (if they exist).</p>
<p>If you encounter any such problems, please post them in the discussion group
or open an issue on GitHub or BitBucket (or send me an email).</p>
<p>There also have been a number of minor API changes.
Please see the README for more information.</p>
</div>
<div class="section" id="new-features">
<h3>New Features</h3>
<ul>
<li><p class="first">official Django 1.3 alpha compatibility</p>
</li>
<li><p class="first"><tt class="docutils literal">PolymorphicModel.__getattribute__</tt> hack removed.
This improves performance considerably as python's __getattribute__
generally causes a pretty large processing overhead. It's gone now.</p>
</li>
<li><p class="first">the <tt class="docutils literal">polymorphic_dumpdata</tt> management command is not needed anymore
and has been disabled, as the regular Django dumpdata command now automatically
works correctly with polymorphic models (for all supported versions of Django).</p>
</li>
<li><p class="first"><tt class="docutils literal">.get_real_instances()</tt> has been elevated to an official part of the API:</p>
<pre class="literal-block">
real_objects = ModelA.objects.get_real_instances(base_objects_list_or_queryset)
</pre>
<p>allows you to turn a queryset or list of base objects into a list of the real instances.
This is useful if e.g. you use <tt class="docutils literal"><span class="pre">ModelA.base_objects.extra(...)</span></tt> and then want to
transform the result to its polymorphic equivalent.</p>
</li>
<li><p class="first"><tt class="docutils literal">translate_polymorphic_Q_object</tt> (see DOCS)</p>
</li>
<li><p class="first">improved testing</p>
</li>
<li><p class="first">Changelog added: CHANGES.rst/html</p>
</li>
</ul>
</div>
<div class="section" id="id2">
<h3>Bugfixes</h3>
<ul class="simple">
<li>Removed requirement for primary key to be an IntegerField.
Thanks to Mathieu Steele and Malthe Borch.</li>
</ul>
</div>
<div class="section" id="api-changes">
<h3>API Changes</h3>
<p><strong>polymorphic_dumpdata</strong></p>
<p>The management command <tt class="docutils literal">polymorphic_dumpdata</tt> is not needed anymore
and has been disabled, as the regular Django dumpdata command now automatically
works correctly with polymorphic models (for all supported versions of Django).</p>
<p><strong>Output of Queryset or Object Printing</strong></p>
<p>In order to improve compatibility with vanilla Django, printing quersets
(__repr__ and __unicode__) does not use django_polymorphic's pretty printing
by default anymore. To get the old behaviour when printing querysets,
you need to replace your model definition:</p>
<pre class="doctest-block">
&gt;&gt;&gt; class Project(PolymorphicModel):
</pre>
<p>by:</p>
<pre class="doctest-block">
&gt;&gt;&gt; class Project(PolymorphicModel, ShowFieldType):
</pre>
<p>The mixin classes for pretty output have been renamed:</p>
<blockquote>
<tt class="docutils literal">ShowFieldTypes, ShowFields, ShowFieldsAndTypes</tt></blockquote>
<p>are now:</p>
<blockquote>
<tt class="docutils literal">ShowFieldType, ShowFieldContent and ShowFieldTypeAndContent</tt></blockquote>
<p>(the old ones still exist for compatibility)</p>
<p><strong>Running the Test suite with Django 1.3</strong></p>
<p>Django 1.3 requires <tt class="docutils literal">python manage.py test polymorphic</tt> instead of
just <tt class="docutils literal">python manage.py test</tt>.</p>
</div>
</div>
<hr class="docutils" />
<div class="section" id="id3">
<h2>2010-2-22</h2>
<p>IMPORTANT: API Changed (import path changed), and Installation Note</p>
<p>The django_polymorphic source code has been restructured
and as a result needs to be installed like a normal Django App
- either via copying the &quot;polymorphic&quot; directory into your
Django project or by running setup.py. Adding 'polymorphic'
to INSTALLED_APPS in settings.py is still optional, however.</p>
<p>The file <cite>polymorphic.py</cite> cannot be used as a standalone
extension module anymore, as is has been split into a number
of smaller files.</p>
<p>Importing works slightly different now: All relevant symbols are
imported directly from 'polymorphic' instead from
'polymorphic.models':</p>
<pre class="literal-block">
# new way
from polymorphic import PolymorphicModel, ...
# old way, doesn't work anymore
from polymorphic.models import PolymorphicModel, ...
</pre>
<ul class="simple">
<li>minor API addition: 'from polymorphic import VERSION, get_version'</li>
</ul>
<div class="section" id="id4">
<h3>New Features</h3>
<p>Python 2.4 compatibility, contributed by Charles Leifer. Thanks!</p>
</div>
<div class="section" id="id5">
<h3>Bugfixes</h3>
<p>Fix: The exception &quot;...has no attribute 'sub_and_superclass_dict'&quot;
could be raised. (This occurred if a subclass defined __init__
and accessed class members before calling the superclass __init__).
Thanks to Mattias Brändström.</p>
<p>Fix: There could be name conflicts if
field_name == model_name.lower() or similar.
Now it is possible to give a field the same name as the class
(like with normal Django models).
(Found through the example provided by Mattias Brändström)</p>
</div>
</div>
<hr class="docutils" />
<div class="section" id="id6">
<h2>2010-2-4</h2>
<div class="section" id="new-features-and-documentation">
<h3>New features (and documentation)</h3>
<p>queryset order_by method added</p>
<p>queryset aggregate() and extra() methods implemented</p>
<p>queryset annotate() method implemented</p>
<p>queryset values(), values_list(), distinct() documented; defer(),
only() allowed (but not yet supported)</p>
<p>setup.py added. Thanks to Andrew Ingram.</p>
<p>More about these additions in the docs:
<a class="reference external" href="http://bserve.webhop.org/wiki/django_polymorphic/doc">http://bserve.webhop.org/wiki/django_polymorphic/doc</a></p>
</div>
<div class="section" id="id7">
<h3>Bugfixes</h3>
<ul class="simple">
<li>fix remaining potential accessor name clashes (but this only works
with Django 1.2+, for 1.1 no changes). Thanks to Andrew Ingram.</li>
<li>fix use of 'id' model field, replaced with 'pk'.</li>
<li>fix select_related bug for objects from derived classes (till now
sel.-r. was just ignored)</li>
</ul>
</div>
<div class="section" id="restrictions-caveats-updated">
<h3>&quot;Restrictions &amp; Caveats&quot; updated</h3>
<ul class="simple">
<li>Django 1.1 only - the names of polymorphic models must be unique
in the whole project, even if they are in two different apps.
This results from a restriction in the Django 1.1 &quot;related_name&quot;
option (fixed in Django 1.2).</li>
<li>Django 1.1 only - when ContentType is used in models, Django's
seralisation or fixtures cannot be used. This issue seems to be
resolved for Django 1.2 (changeset 11863: Fixed #7052, Added
support for natural keys in serialization).</li>
</ul>
</div>
</div>
<hr class="docutils" />
<div class="section" id="id8">
<h2>2010-1-30</h2>
<p>Fixed ContentType related field accessor clash (an error emitted
by model validation) by adding related_name to the ContentType
ForeignKey. This happened if your polymorphc model used a ContentType
ForeignKey. Thanks to Andrew Ingram.</p>
</div>
<hr class="docutils" />
<div class="section" id="id9">
<h2>2010-1-29</h2>
<p>Restructured django_polymorphic into a regular Django add-on
application. This is needed for the management commands, and
also seems to be a generally good idea for future enhancements
as well (and it makes sure the tests are always included).</p>
<p>The <tt class="docutils literal">poly</tt> app - until now being used for test purposes only
- has been renamed to <tt class="docutils literal">polymorphic</tt>. See DOCS.rst
(&quot;installation/testing&quot;) for more info.</p>
</div>
<hr class="docutils" />
<div class="section" id="id10">
<h2>2010-1-28</h2>
<p>Added the polymorphic_dumpdata management command (github issue 4),
for creating fixtures, this should be used instead of
the normal Django dumpdata command.
Thanks to Charles Leifer.</p>
<p>Important: Using ContentType together with dumpdata generally
needs Django 1.2 (important as any polymorphic model uses
ContentType).</p>
</div>
<hr class="docutils" />
<div class="section" id="id11">
<h2>2010-1-26</h2>
<p>IMPORTANT - database schema change (more info in change log).
I hope I got this change in early enough before anyone started
to use polymorphic.py in earnest. Sorry for any inconvenience.
This should be the final DB schema now.</p>
<p>Django's ContentType is now used instead of app-label and model-name
This is a cleaner and more efficient solution
Thanks to Ilya Semenov for the suggestion.</p>
</div>
</div>
</div>
</body>
</html>

756
DOCS.html
View File

@ -1,756 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title></title>
<style type="text/css">
h1, h2, h3, h4,
#table-of-contents
{
color: #47c;
}
h1 { padding-top: 15px; }
h2 { padding-top: 10px; }
h3 { padding-top: 7px; }
a:hover { border-bottom: 1px solid #0066cc; }
a {color: #0066cc; text-decoration: none;}
li {
padding-top: 5px;
padding-bottom: 5px;
}
tt {
color: #080;
}
blockquote tt {
color: #000
}
.first {
margin-top: 0 }
.last {
margin-bottom: 0 }
/*
a.toc-backref {
text-decoration: none ;
color: black }
*/
dd {
margin-bottom: 0.5em }
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em }
div.footer, div.header {
font-size: smaller }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr {
width: 75% }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.line-block {
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option-argument {
font-style: italic }
span.pre {
white-space: pre }
span.problematic {
color: red }
table {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.citation {
border-left: solid thin gray ;
padding-left: 0.5ex }
table.docinfo {
margin: 2em 4em }
table.footnote {
border-left: solid thin black ;
padding-left: 0.5ex }
td, th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
th.docinfo-name, th.field-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap }
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
font-size: 100% }
tt, pre.literal-block, pre.doctest-block {
font-size: 115%;
line-height: 150% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<div class="section" id="polymorphic-models-for-django">
<h1><a class="toc-backref" href="#id1">Polymorphic Models for Django</a></h1>
<div class="contents topic" id="table-of-contents">
<p class="topic-title first">Table of Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#polymorphic-models-for-django" id="id1">Polymorphic Models for Django</a></li>
<li><a class="reference internal" href="#quickstart" id="id2">Quickstart</a></li>
<li><a class="reference internal" href="#list-of-features" id="id3">List of Features</a></li>
<li><a class="reference internal" href="#more-about-installation-testing" id="id4">More about Installation / Testing</a></li>
<li><a class="reference internal" href="#more-polymorphic-functionality" id="id5">More Polymorphic Functionality</a></li>
<li><a class="reference internal" href="#custom-managers-querysets-manager-inheritance" id="id6">Custom Managers, Querysets &amp; Manager Inheritance</a></li>
<li><a class="reference internal" href="#performance-considerations" id="id7">Performance Considerations</a></li>
<li><a class="reference internal" href="#restrictions-caveats" id="id8">Restrictions &amp; Caveats</a></li>
<li><a class="reference internal" href="#project-status" id="id9">Project Status</a></li>
<li><a class="reference internal" href="#links" id="id10">Links</a></li>
</ul>
</div>
</div>
<div class="section" id="quickstart">
<h1><a class="toc-backref" href="#id2">Quickstart</a></h1>
<div class="section" id="install">
<h2>Install</h2>
<p>After uncompressing (if necessary), in the directory &quot;...django_polymorphic&quot;,
execute (on Unix-like systems):</p>
<pre class="literal-block">
sudo python setup.py install
</pre>
</div>
<div class="section" id="make-your-models-polymorphic">
<h2>Make Your Models Polymorphic</h2>
<p>Use <tt class="docutils literal">PolymorphicModel</tt> instead of Django's <tt class="docutils literal">models.Model</tt>, like so:</p>
<pre class="literal-block">
from polymorphic import PolymorphicModel
class Project(PolymorphicModel):
topic = models.CharField(max_length=30)
class ArtProject(Project):
artist = models.CharField(max_length=30)
class ResearchProject(Project):
supervisor = models.CharField(max_length=30)
</pre>
<p>All models inheriting from your polymorphic models will be polymorphic as well.</p>
</div>
<div class="section" id="create-some-objects">
<h2>Create some objects</h2>
<pre class="doctest-block">
&gt;&gt;&gt; Project.objects.create(topic=&quot;Department Party&quot;)
&gt;&gt;&gt; ArtProject.objects.create(topic=&quot;Painting with Tim&quot;, artist=&quot;T. Turner&quot;)
&gt;&gt;&gt; ResearchProject.objects.create(topic=&quot;Swallow Aerodynamics&quot;, supervisor=&quot;Dr. Winter&quot;)
</pre>
</div>
<div class="section" id="get-polymorphic-query-results">
<h2>Get polymorphic query results</h2>
<pre class="doctest-block">
&gt;&gt;&gt; Project.objects.all()
[ &lt;Project: id 1, topic &quot;Department Party&quot;&gt;,
&lt;ArtProject: id 2, topic &quot;Painting with Tim&quot;, artist &quot;T. Turner&quot;&gt;,
&lt;ResearchProject: id 3, topic &quot;Swallow Aerodynamics&quot;, supervisor &quot;Dr. Winter&quot;&gt; ]
</pre>
<p>use <tt class="docutils literal">instance_of</tt> or <tt class="docutils literal">not_instance_of</tt> for narrowing the result to specific subtypes:</p>
<pre class="doctest-block">
&gt;&gt;&gt; Project.objects.instance_of(ArtProject)
[ &lt;ArtProject: id 2, topic &quot;Painting with Tim&quot;, artist &quot;T. Turner&quot;&gt; ]
</pre>
<pre class="doctest-block">
&gt;&gt;&gt; Project.objects.instance_of(ArtProject) | Project.objects.instance_of(ResearchProject)
[ &lt;ArtProject: id 2, topic &quot;Painting with Tim&quot;, artist &quot;T. Turner&quot;&gt;,
&lt;ResearchProject: id 3, topic &quot;Swallow Aerodynamics&quot;, supervisor &quot;Dr. Winter&quot;&gt; ]
</pre>
<p>Polymorphic filtering: Get all projects where Mr. Turner is involved as an artist
or supervisor (note the three underscores):</p>
<pre class="doctest-block">
&gt;&gt;&gt; Project.objects.filter( Q(ArtProject___artist = 'T. Turner') | Q(ResearchProject___supervisor = 'T. Turner') )
[ &lt;ArtProject: id 2, topic &quot;Painting with Tim&quot;, artist &quot;T. Turner&quot;&gt;,
&lt;ResearchProject: id 4, topic &quot;Color Use in Late Cubism&quot;, supervisor &quot;T. Turner&quot;&gt; ]
</pre>
<p>This is basically all you need to know, as django_polymorphic mostly
works fully automatic and just delivers the expected (&quot;pythonic&quot;) results.</p>
<p>Note: In all example output, above and below, for a nicer and more informative
output the <tt class="docutils literal">ShowFieldType</tt> mixin has been used (documented below).</p>
</div>
</div>
<div class="section" id="list-of-features">
<h1><a class="toc-backref" href="#id3">List of Features</a></h1>
<ul class="simple">
<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 (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():
<tt class="docutils literal"><span class="pre">instance_of(...)</span></tt> and <tt class="docutils literal"><span class="pre">not_instance_of(...)</span></tt></li>
<li>Polymorphic filtering/ordering etc., allowing the use of fields of
derived models (&quot;ArtProject___artist&quot;)</li>
<li>Support for user-defined custom managers</li>
<li>Automatic inheritance of custom managers</li>
<li>Support for user-defined custom queryset classes</li>
<li>Non-polymorphic queries if needed, with no other change in
features/behaviour</li>
<li>Combining querysets of different types/models (&quot;qs3 = qs1 | qs2&quot;)</li>
<li>Nice/informative display of polymorphic queryset results</li>
</ul>
</div>
<div class="section" id="more-about-installation-testing">
<h1><a class="toc-backref" href="#id4">More about Installation / Testing</a></h1>
<div class="section" id="requirements">
<h2>Requirements</h2>
<p>Django 1.1 (or later) and Python 2.4 or later. This code has been tested
on Django 1.1 / 1.2 / 1.3 and Python 2.4.6 / 2.5.4 / 2.6.4 on Linux.</p>
</div>
<div class="section" id="included-test-suite">
<h2>Included Test Suite</h2>
<p>The repository (or tar file) contains a complete Django project
that may be used for tests or experiments, without any installation needed.</p>
<p>To run the included test suite, in the directory &quot;...django_polymorphic&quot; execute:</p>
<pre class="literal-block">
./manage test polymorphic
</pre>
<p>The management command <tt class="docutils literal">pcmd.py</tt> in the app <tt class="docutils literal">pexp</tt> can be used
for quick tests or experiments - modify this file (pexp/management/commands/pcmd.py)
to your liking, then run:</p>
<pre class="literal-block">
./manage syncdb # db is created in /var/tmp/... (settings.py)
./manage pcmd
</pre>
</div>
<div class="section" id="installation">
<h2>Installation</h2>
<p>In the directory &quot;...django_polymorphic&quot;, execute <tt class="docutils literal">sudo python setup.py install</tt>.</p>
<p>Alternatively you can simply copy the <tt class="docutils literal">polymorphic</tt> subdirectory
(under &quot;django_polymorphic&quot;) into your Django project dir
(e.g. if you want to distribute your project with more 'batteries included').</p>
<p>If you want to run the test cases in <cite>polymorphic/tests.py</cite>, you need to add
<tt class="docutils literal">polymorphic</tt> to your INSTALLED_APPS setting.</p>
<p>Django's ContentType framework (<tt class="docutils literal">django.contrib.contenttypes</tt>)
needs to be listed in INSTALLED_APPS (usually it already is).</p>
</div>
</div>
<div class="section" id="more-polymorphic-functionality">
<h1><a class="toc-backref" href="#id5">More Polymorphic Functionality</a></h1>
<p>In the examples below, these models are being used:</p>
<pre class="literal-block">
from polymorphic import PolymorphicModel
class ModelA(PolymorphicModel):
field1 = models.CharField(max_length=10)
class ModelB(ModelA):
field2 = models.CharField(max_length=10)
class ModelC(ModelB):
field3 = models.CharField(max_length=10)
</pre>
<div class="section" id="filtering-for-classes-equivalent-to-python-s-isinstance">
<h2>Filtering for classes (equivalent to python's isinstance() ):</h2>
<pre class="doctest-block">
&gt;&gt;&gt; ModelA.objects.instance_of(ModelB)
.
[ &lt;ModelB: id 2, field1 (CharField), field2 (CharField)&gt;,
&lt;ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)&gt; ]
</pre>
<p>In general, including or excluding parts of the inheritance tree:</p>
<pre class="literal-block">
ModelA.objects.instance_of(ModelB [, ModelC ...])
ModelA.objects.not_instance_of(ModelB [, ModelC ...])
</pre>
<p>You can also use this feature in Q-objects (with the same result as above):</p>
<pre class="doctest-block">
&gt;&gt;&gt; ModelA.objects.filter( Q(instance_of=ModelB) )
</pre>
</div>
<div class="section" id="polymorphic-filtering-for-fields-in-derived-classes">
<h2>Polymorphic filtering (for fields in derived classes)</h2>
<p>For example, cherrypicking objects from multiple derived classes
anywhere in the inheritance tree, using Q objects (with the
syntax: <tt class="docutils literal">exact model name + three _ + field name</tt>):</p>
<pre class="doctest-block">
&gt;&gt;&gt; ModelA.objects.filter( Q(ModelB___field2 = 'B2') | Q(ModelC___field3 = 'C3') )
.
[ &lt;ModelB: id 2, field1 (CharField), field2 (CharField)&gt;,
&lt;ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)&gt; ]
</pre>
</div>
<div class="section" id="combining-querysets">
<h2>Combining Querysets</h2>
<p>Querysets could now be regarded as object containers that allow the
aggregation of different object types, very similar to python
lists - as long as the objects are accessed through the manager of
a common base class:</p>
<pre class="doctest-block">
&gt;&gt;&gt; Base.objects.instance_of(ModelX) | Base.objects.instance_of(ModelY)
.
[ &lt;ModelX: id 1, field_x (CharField)&gt;,
&lt;ModelY: id 2, field_y (CharField)&gt; ]
</pre>
</div>
<div class="section" id="manytomanyfield-foreignkey-onetoonefield">
<h2>ManyToManyField, ForeignKey, OneToOneField</h2>
<p>Relationship fields referring to polymorphic models work as
expected: like polymorphic querysets they now always return the
referred objects with the same type/class these were created and
saved as.</p>
<p>E.g., if in your model you define:</p>
<pre class="literal-block">
field1 = OneToOneField(ModelA)
</pre>
<p>then field1 may now also refer to objects of type <tt class="docutils literal">ModelB</tt> or <tt class="docutils literal">ModelC</tt>.</p>
<p>A ManyToManyField example:</p>
<pre class="literal-block">
# The model holding the relation may be any kind of model, polymorphic or not
class RelatingModel(models.Model):
many2many = models.ManyToManyField('ModelA') # ManyToMany relation to a polymorphic model
&gt;&gt;&gt; o=RelatingModel.objects.create()
&gt;&gt;&gt; o.many2many.add(ModelA.objects.get(id=1))
&gt;&gt;&gt; o.many2many.add(ModelB.objects.get(id=2))
&gt;&gt;&gt; o.many2many.add(ModelC.objects.get(id=3))
&gt;&gt;&gt; o.many2many.all()
[ &lt;ModelA: id 1, field1 (CharField)&gt;,
&lt;ModelB: id 2, field1 (CharField), field2 (CharField)&gt;,
&lt;ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)&gt; ]
</pre>
</div>
<div class="section" id="using-third-party-models-without-modifying-them">
<h2>Using Third Party Models (without modifying them)</h2>
<p>Third party models can be used as polymorphic models without
restrictions by subclassing them. E.g. using a third party
model as the root of a polymorphic inheritance tree:</p>
<pre class="literal-block">
from thirdparty import ThirdPartyModel
class MyThirdPartyBaseModel(PolymorhpicModel, ThirdPartyModel):
pass # or add fields
</pre>
<p>Or instead integrating the third party model anywhere into an
existing polymorphic inheritance tree:</p>
<pre class="literal-block">
class MyBaseModel(SomePolymorphicModel):
my_field = models.CharField(max_length=10)
class MyModelWithThirdParty(MyBaseModel, ThirdPartyModel):
pass # or add fields
</pre>
</div>
<div class="section" id="non-polymorphic-queries">
<h2>Non-Polymorphic Queries</h2>
<p>If you insert <tt class="docutils literal">.non_polymorphic()</tt> 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
(<tt class="docutils literal">ModelA</tt> in this example).</p>
<pre class="doctest-block">
&gt;&gt;&gt; qs=ModelA.objects.non_polymorphic().all()
&gt;&gt;&gt; qs
[ &lt;ModelA: id 1, field1 (CharField)&gt;,
&lt;ModelA: id 2, field1 (CharField)&gt;,
&lt;ModelA: id 3, field1 (CharField)&gt; ]
</pre>
<p>There are no other changes in the behaviour of the queryset. For example,
enhancements for <tt class="docutils literal">filter()</tt> or <tt class="docutils literal">instance_of()</tt> etc. still work as expected.
If you do the final step yourself, you get the usual polymorphic result:</p>
<pre class="doctest-block">
&gt;&gt;&gt; ModelA.objects.get_real_instances(qs)
[ &lt;ModelA: id 1, field1 (CharField)&gt;,
&lt;ModelB: id 2, field1 (CharField), field2 (CharField)&gt;,
&lt;ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)&gt; ]
</pre>
</div>
<div class="section" id="about-queryset-methods">
<h2>About Queryset Methods</h2>
<ul class="simple">
<li><tt class="docutils literal">annotate()</tt> and <tt class="docutils literal">aggregate()</tt> work just as usual, with the
addition that the <tt class="docutils literal">ModelX___field</tt> syntax can be used for the
keyword arguments (but not for the non-keyword arguments).</li>
<li><tt class="docutils literal">order_by()</tt> now similarly supports the <tt class="docutils literal">ModelX___field</tt> syntax
for specifying ordering through a field in a submodel.</li>
<li><tt class="docutils literal">distinct()</tt> works as expected. It only regards the fields of
the base class, but this should never make a difference.</li>
<li><tt class="docutils literal">select_related()</tt> works just as usual, but it can not (yet) be used
to select relations in derived models
(like <tt class="docutils literal"><span class="pre">ModelA.objects.select_related('ModelC___fieldxy')</span></tt> )</li>
<li><tt class="docutils literal">extra()</tt> works as expected (it returns polymorphic results) but
currently has one restriction: The resulting objects are required to have
a unique primary key within the result set - otherwise an error is thrown
(this case could be made to work, however it may be mostly unneeded)..
The keyword-argument &quot;polymorphic&quot; is no longer supported.
You can get back the old non-polymorphic behaviour (before V1.0)
by using <tt class="docutils literal"><span class="pre">ModelA.objects.non_polymorphic().extra(...)</span></tt>.</li>
<li><tt class="docutils literal">get_real_instances()</tt> allows you to turn a
queryset or list of base model objects efficiently into the real objects.
For example, you could do <tt class="docutils literal"><span class="pre">base_objects_queryset=ModelA.extra(...).non_polymorphic()</span></tt>
and then call <tt class="docutils literal">real_objects=base_objects_queryset.get_real_instances()</tt>.Or alternatively
.``real_objects=ModelA.objects..get_real_instances(base_objects_queryset_or_object_list)``</li>
<li><tt class="docutils literal">values()</tt> &amp; <tt class="docutils literal">values_list()</tt> currently do not return polymorphic
results. This may change in the future however. If you want to use these
methods now, it's best if you use <tt class="docutils literal"><span class="pre">Model.base_objects.values...</span></tt> as
this is guaranteed to not change.</li>
<li><tt class="docutils literal">defer()</tt> and <tt class="docutils literal">only()</tt> are not yet supported (support will be added
in the future).</li>
</ul>
</div>
<div class="section" id="using-enhanced-q-objects-in-any-places">
<h2>Using enhanced Q-objects in any Places</h2>
<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">
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>
<p>In order to get the output as seen in all examples here, you need to use the
ShowFieldType class mixin:</p>
<pre class="literal-block">
from polymorphic import PolymorphicModel, ShowFieldType
class ModelA(ShowFieldType, PolymorphicModel):
field1 = models.CharField(max_length=10)
</pre>
<p>You may also use ShowFieldContent or ShowFieldTypeAndContent to display
additional information when printing querysets (or converting them to text).</p>
<p>When showing field contents, they will be truncated to 20 characters. You can
modify this behaviour by setting a class variable in your model like this:</p>
<pre class="literal-block">
class ModelA(ShowFieldType, PolymorphicModel):
polymorphic_showfield_max_field_width = 20
...
</pre>
<p>Similarly, pre-V1.0 output formatting can be re-estated by using
<tt class="docutils literal">polymorphic_showfield_old_format = True</tt>.</p>
</div>
</div>
<div class="section" id="custom-managers-querysets-manager-inheritance">
<h1><a class="toc-backref" href="#id6">Custom Managers, Querysets &amp; Manager Inheritance</a></h1>
<div class="section" id="using-a-custom-manager">
<h2>Using a Custom Manager</h2>
<p>A nice feature of Django is the possibility to define one's own custom object managers.
This is fully supported with django_polymorphic: For creating a custom polymorphic
manager class, just derive your manager from <tt class="docutils literal">PolymorphicManager</tt> instead of
<tt class="docutils literal">models.Manager</tt>. As with vanilla Django, in your model class, you should
explicitly add the default manager first, and then your custom manager:</p>
<pre class="literal-block">
from polymorphic import PolymorphicModel, PolymorphicManager
class TimeOrderedManager(PolymorphicManager):
def get_query_set(self):
qs = super(TimeOrderedManager,self).get_query_set()
return qs.order_by('-start_date') # order the queryset
def most_recent(self):
qs = self.get_query_set() # get my ordered queryset
return qs[:10] # limit =&gt; get ten most recent entries
class Project(PolymorphicModel):
objects = PolymorphicManager() # add the default polymorphic manager first
objects_ordered = TimeOrderedManager() # then add your own manager
start_date = DateTimeField() # project start is this date/time
</pre>
<p>The first manager defined ('objects' in the example) is used by
Django as automatic manager for several purposes, including accessing
related objects. It must not filter objects and it's safest to use
the plain <tt class="docutils literal">PolymorphicManager</tt> here.</p>
</div>
<div class="section" id="manager-inheritance">
<h2>Manager Inheritance</h2>
<p>Polymorphic models inherit/propagate all managers from their
base models, as long as these are polymorphic. This means that all
managers defined in polymorphic base models continue to work as
expected in models inheriting from this base model:</p>
<pre class="literal-block">
from polymorphic import PolymorphicModel, PolymorphicManager
class TimeOrderedManager(PolymorphicManager):
def get_query_set(self):
qs = super(TimeOrderedManager,self).get_query_set()
return qs.order_by('-start_date') # order the queryset
def most_recent(self):
qs = self.get_query_set() # get my ordered queryset
return qs[:10] # limit =&gt; get ten most recent entries
class Project(PolymorphicModel):
objects = PolymorphicManager() # add the default polymorphic manager first
objects_ordered = TimeOrderedManager() # then add your own manager
start_date = DateTimeField() # project start is this date/time
class ArtProject(Project): # inherit from Project, inheriting its fields and managers
artist = models.CharField(max_length=30)
</pre>
<p>ArtProject inherited the managers <tt class="docutils literal">objects</tt> and <tt class="docutils literal">objects_ordered</tt> from Project.</p>
<p><tt class="docutils literal">ArtProject.objects_ordered.all()</tt> will return all art projects ordered
regarding their start time and <tt class="docutils literal">ArtProject.objects_ordered.most_recent()</tt>
will return the ten most recent art projects.
.</p>
</div>
<div class="section" id="using-a-custom-queryset-class">
<h2>Using a Custom Queryset Class</h2>
<p>The <tt class="docutils literal">PolymorphicManager</tt> class accepts one initialization argument,
which is the queryset class the manager should use. Just as with vanilla Django,
you may define your own custom queryset classes. Just use PolymorphicQuerySet
instead of Django's QuerySet as the base class:</p>
<pre class="literal-block">
from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet
class MyQuerySet(PolymorphicQuerySet):
def my_queryset_method(...):
...
class MyModel(PolymorphicModel):
my_objects=PolymorphicManager(MyQuerySet)
...
</pre>
</div>
</div>
<div class="section" id="performance-considerations">
<h1><a class="toc-backref" href="#id7">Performance Considerations</a></h1>
<p>The current implementation is rather simple and does not use any
custom SQL or Django DB layer internals - it is purely based on the
standard Django ORM.</p>
<p>Specifically, the query:</p>
<pre class="literal-block">
result_objects = list( ModelA.objects.filter(...) )
</pre>
<p>performs one SQL query to retrieve <tt class="docutils literal">ModelA</tt> objects and one additional
query for each unique derived class occurring in result_objects.
The best case for retrieving 100 objects is 1 SQL query if all are
class <tt class="docutils literal">ModelA</tt>. If 50 objects are <tt class="docutils literal">ModelA</tt> and 50 are <tt class="docutils literal">ModelB</tt>, then
two queries are executed. The pathological worst case is 101 db queries if
result_objects contains 100 different object types (with all of them
subclasses of <tt class="docutils literal">ModelA</tt>).</p>
<p>Usually, when Django users create their own polymorphic ad-hoc solution
without a tool like django_polymorphic, this usually results in a variation of</p>
<pre class="literal-block">
result_objects = [ o.get_real_instance() for o in BaseModel.objects.filter(...) ]
</pre>
<p>which has very bad performance, as it introduces one additional
SQL query for every object in the result which is not of class <tt class="docutils literal">BaseModel</tt>.</p>
<p>Compared to these solutions, django_polymorphic has the advantage
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 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.
This is independent of django_polymorphic and affects all uses of
multi table Model inheritance.</p>
<p>Concrete benchmark results are forthcoming (please see discussion forum).</p>
<p>Please also see this <a class="reference external" href="http://www.jacobian.org/writing/concrete-inheritance/">post (and comments) from Jacob Kaplan-Moss</a>.</p>
</div>
</div>
<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.
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>
<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
with diamond shaped multiple model inheritance with Django models
(tested with V1.1 - V1.3).
An example is here: <a class="reference external" href="http://code.djangoproject.com/ticket/10808">http://code.djangoproject.com/ticket/10808</a>.
This problem is aggravated when trying to enhance models.Model
by subclassing it instead of modifying Django core (as we do here
with PolymorphicModel).</li>
<li>The enhanced filter-definitions/Q-objects only work as arguments
for the methods of the polymorphic querysets. Please see above
for <tt class="docutils literal">translate_polymorphic_Q_object</tt>.</li>
<li>A reference (<tt class="docutils literal">ContentType</tt>) to the real/leaf model is stored
in the base model (the base model directly inheriting from
PolymorphicModel). You need to be aware of this when using the
<tt class="docutils literal">dumpdata</tt> management command or any other low-level
database operations. E.g. if you rename models or apps or copy
objects from one database to another, then Django's ContentType
table needs to be corrected/copied too. This is of course generally
the case for any models using Django's ContentType.</li>
<li>Django 1.1 only - the names of polymorphic models must be unique
in the whole project, even if they are in two different apps.
This results from a restriction in the Django 1.1 &quot;related_name&quot;
option (fixed in Django 1.2).</li>
<li>Django 1.1 only - when ContentType is used in models, Django's
seralisation or fixtures cannot be used (all polymorphic models
use ContentType). This issue seems to be resolved for Django 1.2
(changeset 11863: Fixed #7052, Added support for natural keys in serialization).<ul>
<li><a class="reference external" href="http://code.djangoproject.com/ticket/7052">http://code.djangoproject.com/ticket/7052</a></li>
<li><a class="reference external" href="http://stackoverflow.com/questions/853796/problems-with-contenttypes-when-loading-a-fixture-in-django">http://stackoverflow.com/questions/853796/problems-with-contenttypes-when-loading-a-fixture-in-django</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="project-status">
<h1><a class="toc-backref" href="#id9">Project Status</a></h1>
<p>Django_polymorphic works well for a considerable number of users now,
and no major problems have shown up for many months.
The API can be considered stable beginning with the V1.0 release.</p>
</div>
<div class="section" id="links">
<h1><a class="toc-backref" href="#id10">Links</a></h1>
<ul class="simple">
<li><a class="reference external" href="http://code.djangoproject.com/wiki/ModelInheritance">http://code.djangoproject.com/wiki/ModelInheritance</a></li>
<li><a class="reference external" href="http://lazypython.blogspot.com/2009/02/second-look-at-inheritance-and.html">http://lazypython.blogspot.com/2009/02/second-look-at-inheritance-and.html</a></li>
<li><a class="reference external" href="http://www.djangosnippets.org/snippets/1031/">http://www.djangosnippets.org/snippets/1031/</a></li>
<li><a class="reference external" href="http://www.djangosnippets.org/snippets/1034/">http://www.djangosnippets.org/snippets/1034/</a></li>
<li><a class="reference external" href="http://groups.google.com/group/django-developers/browse_frm/thread/7d40ad373ebfa912/a20fabc661b7035d?lnk=gst&amp;q=model+inheritance+CORBA#a20fabc661b7035d">http://groups.google.com/group/django-developers/browse_frm/thread/7d40ad373ebfa912/a20fabc661b7035d?lnk=gst&amp;q=model+inheritance+CORBA#a20fabc661b7035d</a></li>
<li><a class="reference external" href="http://groups.google.com/group/django-developers/browse_thread/thread/9bc2aaec0796f4e0/0b92971ffc0aa6f8?lnk=gst&amp;q=inheritance#0b92971ffc0aa6f8">http://groups.google.com/group/django-developers/browse_thread/thread/9bc2aaec0796f4e0/0b92971ffc0aa6f8?lnk=gst&amp;q=inheritance#0b92971ffc0aa6f8</a></li>
<li><a class="reference external" href="http://groups.google.com/group/django-developers/browse_thread/thread/3947c594100c4adb/d8c0af3dacad412d?lnk=gst&amp;q=inheritance#d8c0af3dacad412d">http://groups.google.com/group/django-developers/browse_thread/thread/3947c594100c4adb/d8c0af3dacad412d?lnk=gst&amp;q=inheritance#d8c0af3dacad412d</a></li>
<li><a class="reference external" href="http://groups.google.com/group/django-users/browse_thread/thread/52f72cffebb705e/b76c9d8c89a5574f">http://groups.google.com/group/django-users/browse_thread/thread/52f72cffebb705e/b76c9d8c89a5574f</a></li>
<li><a class="reference external" href="http://peterbraden.co.uk/article/django-inheritance">http://peterbraden.co.uk/article/django-inheritance</a></li>
<li><a class="reference external" href="http://www.hopelessgeek.com/2009/11/25/a-hack-for-multi-table-inheritance-in-django">http://www.hopelessgeek.com/2009/11/25/a-hack-for-multi-table-inheritance-in-django</a></li>
<li><a class="reference external" href="http://stackoverflow.com/questions/929029/how-do-i-access-the-child-classes-of-an-object-in-django-without-knowing-the-name/929982#929982">http://stackoverflow.com/questions/929029/how-do-i-access-the-child-classes-of-an-object-in-django-without-knowing-the-name/929982#929982</a></li>
<li><a class="reference external" href="http://stackoverflow.com/questions/1581024/django-inheritance-how-to-have-one-method-for-all-subclasses">http://stackoverflow.com/questions/1581024/django-inheritance-how-to-have-one-method-for-all-subclasses</a></li>
<li><a class="reference external" href="http://groups.google.com/group/django-users/browse_thread/thread/cbdaf2273781ccab/e676a537d735d9ef?lnk=gst&amp;q=polymorphic#e676a537d735d9ef">http://groups.google.com/group/django-users/browse_thread/thread/cbdaf2273781ccab/e676a537d735d9ef?lnk=gst&amp;q=polymorphic#e676a537d735d9ef</a></li>
<li><a class="reference external" href="http://groups.google.com/group/django-users/browse_thread/thread/52f72cffebb705e/bc18c18b2e83881e?lnk=gst&amp;q=model+inheritance#bc18c18b2e83881e">http://groups.google.com/group/django-users/browse_thread/thread/52f72cffebb705e/bc18c18b2e83881e?lnk=gst&amp;q=model+inheritance#bc18c18b2e83881e</a></li>
<li><a class="reference external" href="http://code.djangoproject.com/ticket/10808">http://code.djangoproject.com/ticket/10808</a></li>
<li><a class="reference external" href="http://code.djangoproject.com/ticket/7270">http://code.djangoproject.com/ticket/7270</a></li>
</ul>
</div>
</div>
</body>
</html>

View File

@ -1,411 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title></title>
<style type="text/css">
h1, h2, h3, h4,
#table-of-contents
{
color: #47c;
}
h1 { padding-top: 15px; }
h2 { padding-top: 10px; }
h3 { padding-top: 7px; }
a:hover { border-bottom: 1px solid #0066cc; }
a {color: #0066cc; text-decoration: none;}
li {
padding-top: 5px;
padding-bottom: 5px;
}
tt {
color: #080;
}
blockquote tt {
color: #000
}
.first {
margin-top: 0 }
.last {
margin-bottom: 0 }
/*
a.toc-backref {
text-decoration: none ;
color: black }
*/
dd {
margin-bottom: 0.5em }
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
color: red ;
font-weight: bold ;
font-family: sans-serif }
div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em }
div.footer, div.header {
font-size: smaller }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr {
width: 75% }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font-family: serif ;
font-size: 100% }
pre.line-block {
font-family: serif ;
font-size: 100% }
pre.literal-block, pre.doctest-block {
margin-left: 2em ;
margin-right: 2em ;
background-color: #eeeeee }
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option-argument {
font-style: italic }
span.pre {
white-space: pre }
span.problematic {
color: red }
table {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.citation {
border-left: solid thin gray ;
padding-left: 0.5ex }
table.docinfo {
margin: 2em 4em }
table.footnote {
border-left: solid thin black ;
padding-left: 0.5ex }
td, th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
th.docinfo-name, th.field-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap }
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
font-size: 100% }
tt, pre.literal-block, pre.doctest-block {
font-size: 115%;
line-height: 150% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<div class="section" id="polymorphic-models-for-django">
<h1>Polymorphic Models for Django</h1>
<div class="section" id="quick-start-docs-contributing">
<h2>Quick Start, Docs, Contributing</h2>
<ul class="simple">
<li><a class="reference external" href="#good-for">What is django_polymorphic good for?</a></li>
<li><a class="reference external" href="http://bserve.webhop.org/django_polymorphic/DOCS.html#quickstart">Quickstart</a>, or the complete <a class="reference external" href="http://bserve.webhop.org/django_polymorphic/DOCS.html">Installation and Usage Docs</a></li>
<li><a class="reference external" href="http://groups.google.de/group/django-polymorphic/topics">Release Notes, News and Discussion</a> (Google Group) or <a class="reference external" href="http://bserve.webhop.org/django_polymorphic/CHANGES.html">Changelog</a></li>
<li>Download from <a class="reference external" href="http://github.com/bconstantin/django_polymorphic">GitHub</a> or <a class="reference external" href="http://bitbucket.org/bconstantin/django_polymorphic">Bitbucket</a>, or as <a class="reference external" href="http://github.com/bconstantin/django_polymorphic/tarball/master">TGZ</a> or <a class="reference external" href="http://github.com/bconstantin/django_polymorphic/zipball/master">ZIP</a></li>
<li>Improve django_polymorphic, report issues, discuss, patch or fork (<a class="reference external" href="http://github.com/bconstantin/django_polymorphic">GitHub</a>, <a class="reference external" href="http://bitbucket.org/bconstantin/django_polymorphic">Bitbucket</a>, <a class="reference external" href="http://groups.google.de/group/django-polymorphic/topics">Group</a>, <a class="reference external" href="http://github.com/bconstantin/django_polymorphic/tree/master/setup.py">Mail</a>)</li>
</ul>
</div>
<div class="section" id="id1">
<span id="good-for"></span><h2>What is django_polymorphic good for?</h2>
<p>Let's assume the models <tt class="docutils literal">ArtProject</tt> and <tt class="docutils literal">ResearchProject</tt> are derived
from the model <tt class="docutils literal">Project</tt>, and let's store one of each into the database:</p>
<pre class="doctest-block">
&gt;&gt;&gt; Project.objects.create(topic=&quot;Department Party&quot;)
&gt;&gt;&gt; ArtProject.objects.create(topic=&quot;Painting with Tim&quot;, artist=&quot;T. Turner&quot;)
&gt;&gt;&gt; ResearchProject.objects.create(topic=&quot;Swallow Aerodynamics&quot;, supervisor=&quot;Dr. Winter&quot;)
</pre>
<p>If we want to retrieve all our projects, we do:</p>
<pre class="doctest-block">
&gt;&gt;&gt; Project.objects.all()
</pre>
<p>Using django_polymorphic, we simply get what we stored:</p>
<pre class="literal-block">
[ &lt;Project: id 1, topic &quot;Department Party&quot;&gt;,
&lt;ArtProject: id 2, topic &quot;Painting with Tim&quot;, artist &quot;T. Turner&quot;&gt;,
&lt;ResearchProject: id 3, topic &quot;Swallow Aerodynamics&quot;, supervisor &quot;Dr. Winter&quot;&gt; ]
</pre>
<p>Using vanilla Django, we get incomplete objects, which is probably not what we wanted:</p>
<pre class="literal-block">
[ &lt;Project: id 1, topic &quot;Department Party&quot;&gt;,
&lt;Project: id 2, topic &quot;Painting with Tim&quot;&gt;,
&lt;Project: id 3, topic &quot;Swallow Aerodynamics&quot;&gt; ]
</pre>
<p>It's very similar for ForeignKeys, ManyToManyFields or OneToOneFields.</p>
<p>In general, the effect of django_polymorphic is twofold:</p>
<p>On one hand it makes sure that model inheritance just works as you
expect, by simply ensuring that you always get back exactly the same
objects from the database you stored there - regardless how you access
them, making model inheritance much more &quot;pythonic&quot;.
This can save you a lot of unpleasant workarounds that tend to
make your code messy, error-prone, and slow.</p>
<p>On the other hand, together with some small API additions to the Django
ORM, django_polymorphic enables a much more expressive and intuitive
programming style and also very advanced object oriented designs
that are not possible with vanilla Django.</p>
<p>Fortunately, most of the heavy duty machinery that is needed for this
functionality is already present in the original Django database layer.
Django_polymorphic adds a rather thin layer above that in order
to make real OO fully automatic and very easy to use.</p>
<p>There is a catch however, which applies to concrete model inheritance
in general: Current DBM systems like PostgreSQL or MySQL are not very
good at processing the required sql queries and can be rather slow in
many cases. Concrete benchmarks are forthcoming (please see
discussion forum).</p>
<p>For more information, please look at <a class="reference external" href="http://bserve.webhop.org/django_polymorphic/DOCS.html#quickstart">Quickstart</a> or at the complete
<a class="reference external" href="http://bserve.webhop.org/django_polymorphic/DOCS.html">Installation and Usage Docs</a> and also see the <a class="reference external" href="http://bserve.webhop.org/django_polymorphic/DOCS.html#restrictions">restrictions and caveats</a>.</p>
</div>
<div class="section" id="this-is-a-v1-0-beta-testing-release">
<h2>This is a V1.0 Beta/Testing Release</h2>
<p>The release contains a considerable amount of changes in some of the more
critical parts of the software. It's intended for testing and development
environments and not for production environments. For these, it's best to
wait a few weeks for the proper V1.0 release, to allow some time for any
potential problems to turn up (if they exist).</p>
<p>If you encounter any problems or have suggestions regarding the API or the
changes in this beta, please post them in the <a class="reference external" href="http://groups.google.de/group/django-polymorphic/topics">discussion group</a>
or open an issue on <a class="reference external" href="http://github.com/bconstantin/django_polymorphic">GitHub</a> or <a class="reference external" href="http://bitbucket.org/bconstantin/django_polymorphic">BitBucket</a> (or send me an email).</p>
</div>
</div>
<div class="section" id="license">
<h1>License</h1>
<p>Django_polymorphic uses the same license as Django (BSD-like).</p>
</div>
<div class="section" id="api-changes-additions">
<h1>API Changes &amp; Additions</h1>
<div class="section" id="november-11-2010-v1-0-api-changes">
<h2>November 11 2010, V1.0 API Changes</h2>
<div class="section" id="extra-queryset-method">
<h3>extra() queryset method</h3>
<p><tt class="docutils literal">.extra()</tt> has been re-implemented. Now it's polymorphic by
default and works (nearly) without restrictions (please see docs). This is a (very)
incompatible API change regarding previous versions of django_polymorphic.
Support for the <tt class="docutils literal">polymorphic</tt> keyword parameter has been removed.
You can get back the non-polymorphic behaviour by using
<tt class="docutils literal"><span class="pre">ModelA.objects.non_polymorphic().extra()</span></tt>.</p>
</div>
<div class="section" id="no-pretty-printing-of-querysets-by-default">
<h3>No Pretty-Printing of Querysets by default</h3>
<p>In order to improve compatibility with vanilla Django, printing quersets
(__repr__ and __unicode__) does not use django_polymorphic's pretty printing
by default anymore. To get the old behaviour when printing querysets,
you need to replace your model definition:</p>
<pre class="doctest-block">
&gt;&gt;&gt; class Project(PolymorphicModel):
</pre>
<p>by:</p>
<pre class="doctest-block">
&gt;&gt;&gt; class Project(PolymorphicModel, ShowFieldType):
</pre>
<p>The mixin classes for pretty output have been renamed:</p>
<blockquote>
<tt class="docutils literal">ShowFieldTypes, ShowFields, ShowFieldsAndTypes</tt></blockquote>
<p>are now:</p>
<blockquote>
<tt class="docutils literal">ShowFieldType, ShowFieldContent and ShowFieldTypeAndContent</tt></blockquote>
<p>(the old ones still exist for compatibility)</p>
</div>
<div class="section" id="pretty-printing-output-format-changed">
<h3>Pretty-Printing Output Format Changed</h3>
<p><tt class="docutils literal">ShowFieldContent</tt> and <tt class="docutils literal">ShowFieldTypeAndContent</tt> now
use a slightly different output format. If this causes too much trouble for
your test cases, you can get the old behaviour back (mostly) by adding
<tt class="docutils literal">polymorphic_showfield_old_format = True</tt> to your model definitions.
<tt class="docutils literal"><span class="pre">ShowField...</span></tt> now also produces more informative output for custom
primary keys.</p>
</div>
<div class="section" id="polymorphic-dumpdata">
<h3>polymorphic_dumpdata</h3>
<p>The <tt class="docutils literal">polymorphic_dumpdata</tt> management command is not needed anymore
and has been disabled, as the regular Django dumpdata command now automatically
works correctly with polymorphic models (for all supported versions of Django).</p>
</div>
<div class="section" id="running-the-test-suite-with-django-1-3">
<h3>Running the Test suite with Django 1.3</h3>
<p>Django 1.3 requires <tt class="docutils literal">python manage.py test polymorphic</tt> instead of
just <tt class="docutils literal">python manage.py test</tt>.</p>
</div>
</div>
<div class="section" id="november-01-2010-v1-0-api-additions">
<h2>November 01 2010, V1.0 API Additions</h2>
<ul>
<li><p class="first"><tt class="docutils literal">.non_polymorphic()</tt> queryset member function added. This is preferable to
using <tt class="docutils literal"><span class="pre">.base_objects...</span></tt>, as it just makes the resulting queryset non-polymorphic
and does not change anything else in the behaviour of the manager used (while
<tt class="docutils literal">.base_objects</tt> is just a different manager).</p>
</li>
<li><p class="first"><tt class="docutils literal">.get_real_instances()</tt> has been elevated to an official part of the API.
It allows you to turn a queryset or list of base objects into a list of the real instances.
This is useful if e.g. you use <tt class="docutils literal"><span class="pre">ModelA.objects.non_polymorphic().extra(...)</span></tt> and then want to
transform the result to its polymorphic equivalent:</p>
<pre class="doctest-block">
&gt;&gt;&gt; qs = ModelA.objects.all().non_polymorphic()
&gt;&gt;&gt; real_objects = qs.get_real_instances()
</pre>
<p>is equivalent to:</p>
<pre class="doctest-block">
&gt;&gt;&gt; real_objects = ModelA.objects.all()
</pre>
<p>Instead of <tt class="docutils literal">qs.get_real_instances()</tt>, <tt class="docutils literal">ModelA.objects.get_real_instances(qs)</tt> may be used
as well. In the latter case, <tt class="docutils literal">qs</tt> may be any list of objects of type ModelA.</p>
</li>
<li><p class="first"><tt class="docutils literal">translate_polymorphic_Q_object</tt> (see DOCS)</p>
</li>
</ul>
</div>
<div class="section" id="february-22-2010-installation-note">
<h2>February 22 2010, Installation Note</h2>
<p>The django_polymorphic source code has been restructured
and as a result needs to be installed like a normal Django App
- either via copying the &quot;polymorphic&quot; directory into your
Django project or by running setup.py. Adding 'polymorphic'
to INSTALLED_APPS in settings.py is still optional, however.</p>
<p>The file <cite>polymorphic.py</cite> cannot be used as a standalone
extension module anymore (as is has been split into a number
of smaller files).</p>
<p>Importing works slightly different now: All relevant symbols are
imported directly from 'polymorphic' instead from
'polymorphic.models':</p>
<pre class="literal-block">
# new way
from polymorphic import PolymorphicModel, ...
# old way, doesn't work anymore
from polymorphic.models import PolymorphicModel, ...
</pre>
</div>
<div class="section" id="january-26-2010-database-schema-change">
<h2>January 26 2010: Database Schema Change</h2>
<p>The update from January 26 changed the database schema (more info in the <a class="reference external" href="http://github.com/bconstantin/django_polymorphic/commit/c2b420aea06637966a208329ef7ec853889fa4c7">commit-log</a>).
Sorry for any inconvenience. But this should be the final DB schema now.</p>
</div>
</div>
</div>
</body>
</html>