Permalink
Browse files

Restructured django_polymorphic into a regular add-on application.

This is needed for the management commands, and also seems
to be a generally good idea for future viablity as well.
Also misc documentation updates.
  • Loading branch information...
1 parent dd84e91 commit 8bdda93e76133ced44327f89703c7305955a5119 @bconstantin bconstantin committed Jan 28, 2010
View
@@ -8,7 +8,9 @@ Requirements
------------
Django 1.1 (or later) and Python 2.5 (or later). This code has been tested
-on Django 1.1.1 / 1.2 alpha and Python 2.5.4 / 2.6.4 on Linux.
+on Django 1.1.1 / 1.2 alpha and Python 2.5.4 / 2.6.4 on Linux.
+Django's ContentType framework is used (part of Django).
+
Testing
-------
@@ -18,20 +20,28 @@ that may be used for tests or experiments.
To run the included test suite, execute::
- ./manage test poly
+ ./manage test polymorphic
-'management/commands/polycmd.py' can be used for experiments
-- modify this file to your liking, then run::
+The management command ``pcmd.py`` in the app ``pexp`` (Polymorphic EXPerimenting)
+can be used for experiments - modify this file (pexp/management/commands/pcmd.py)
+to your liking, then run::
./manage syncdb # db is created in /var/tmp/... (settings.py)
- ./manage polycmd
+ ./manage pcmd
Using polymorphic models in your own projects
---------------------------------------------
-Copy polymorphic.py (from the 'poly' dir) into a directory from where
-you can import it, like your app directory (where your models.py and
-views.py files live).
+The best way for now is probably to just copy the ``polymorphic`` directory
+into your project dir. If you want to use the management command
+``polymorphic_dumpdata``, then you also need to add ``polymorphic``
+to your INSTALLED_APPS setting. The ContentType framework
+(``django.contrib.contenttypes``) needs to be listed in INSTALLED_APPS
+as well (usually it already is).
+
+It's also still possible to use ``polymorphic.py`` only, as a single file
+add-on module, copied to somewhere where it can be imported (like your
+own app dir).
Defining Polymorphic Models
@@ -41,7 +51,7 @@ To make models polymorphic, use ``PolymorphicModel`` instead of Django's
``models.Model`` as the superclass of your base model. All models
inheriting from your base class will be polymorphic as well::
- from polymorphic import PolymorphicModel
+ from polymorphic.models import PolymorphicModel
class ModelA(PolymorphicModel):
field1 = models.CharField(max_length=10)
@@ -177,6 +187,15 @@ Non-Polymorphic Queries
Django manager. Of course, arbitrary custom managers may be
added to the models as well.
+manage.py dumpdata
+------------------
+
+ Django's standard ``dumpdata`` requires non-polymorphic
+ behaviour from the querysets it uses and produces incomplete
+ results with polymorphic models. Django_polymorphic includes
+ a slightly modified version, named ``polymorphic_dumpdata``.
+ Just use this command instead of Django's (see "installation/testing").
+
Custom Managers, Querysets & Inheritance
========================================
@@ -205,23 +224,21 @@ the plain ``PolymorphicManager`` here.
Manager Inheritance / Propagation
---------------------------------
-Polymorphic models unconditionally inherit all managers from their
-base models (as long as these are polymorphic).
+Polymorphic models unconditionally propagate (or inherit) all managers from
+their base models, as long as these are polymorphic. This means that all
+managers inherited from polymorphic base models work just the same as if
+they were defined in the new model.
An example (inheriting from MyModel above)::
class MyModel2(MyModel):
pass
- # Managers inherited from MyModel, delivering MyModel2 (and subclass) objects
+ # Managers inherited from MyModel:
+ # the regular 'objects' manager and the custom 'ordered_objects' manager
>>> MyModel2.objects.all()
>>> MyModel2.ordered_objects.all()
-Perhaps a more correct way to describe this: With polymorphic models the
-managers are always fully propagated from all polymorphic base models
-(as strictly speaking all managers are always inherited with Django models).
-
-
Using a Custom Queryset Class
-----------------------------
@@ -377,6 +394,10 @@ Restrictions & Caveats
ContentType table needs to be corrected too, if the db content
should stay usable after the rename.
++ The stability of the ``ContentType`` ids when combined with Django's
+ serialisation / fixtures has not yet been sufficiently
+ investigated (please see issue 4 on github).
+
+ For all objects that are not instances of the base class type, but
instances of a subclass, the base class fields are currently
transferred twice from the database (an artefact of the current
@@ -393,13 +414,13 @@ Restrictions & Caveats
In General
----------
-It is important to consider that this code is still very new and experimental.
+It's important to consider that this code is still very new and experimental.
-It has, however, been integrated into one larger system where all seems to work flawlessly
-so far. A small number of people tested this code for their purposes and reported that it
-works well for them.
+Right now it's suitable only for the more enterprising early adopters.
-Right now this module is suitable only for the more enterprising early adopters.
+It does seem to work well for a number of people (including me), but
+it's still very early and API changes, code reorganisations or further
+schema changes are still a possibility.
Links
View
@@ -8,48 +8,76 @@
Usage, Examples, Installation & Documentation, Links
----------------------------------------------------
-* Documentation_ and Overview_
-* `Discussion, Questions, Suggestions`_
-* GitHub_ - Bitbucket_ - `Download as TGZ`_ or ZIP_
+* Please see the `Documentation and Examples`_ (or the short `Overview`_)
+* If you have comments or suggestions: `Discussion, Comments, Suggestions`_
+* The code can be found on GitHub_ and Bitbucket_, or downloaded as TGZ_ or ZIP_
-.. _Documentation: http://bserve.webhop.org/wiki/django_polymorphic/doc
+.. _Documentation and Examples: http://bserve.webhop.org/wiki/django_polymorphic/doc
.. _Discussion, Questions, Suggestions: http://django-polymorphic.blogspot.com/2010/01/messages.html
.. _GitHub: http://github.com/bconstantin/django_polymorphic
.. _Bitbucket: http://bitbucket.org/bconstantin/django_polymorphic
-.. _Download as TGZ: http://github.com/bconstantin/django_polymorphic/tarball/master
+.. _TGZ: http://github.com/bconstantin/django_polymorphic/tarball/master
.. _ZIP: http://github.com/bconstantin/django_polymorphic/zipball/master
.. _Overview: http://bserve.webhop.org/wiki/django_polymorphic
What is django_polymorphic good for?
------------------------------------
-If ``ArtProject`` and ``ResearchProject`` inherit from the model ``Project``:
+It causes objects being retrieved from the database to always be returned back
+with the same type/class and fields they were created and saved with.
->>> Project.objects.all()
-.
-[ <Project: id 1, topic: "John's Gathering">,
- <ArtProject: id 2, topic: "Sculpting with Tim", artist: "T. Turner">,
- <ResearchProject: id 3, topic: "Swallow Aerodynamics", supervisor: "Dr. Winter"> ]
+Example:
+If ``ArtProject`` and ``ResearchProject`` inherit from the model ``Project``,
+and we have saved one of each into the database::
-In general, objects retrieved from the database are always returned back
-with the same type/class and fields they were created and saved with.
+ >>> Project.objects.all()
+ .
+ [ <Project: id 1, topic: "John's Gathering">,
+ <ArtProject: id 2, topic: "Sculpting with Tim", artist: "T. Turner">,
+ <ResearchProject: id 3, topic: "Swallow Aerodynamics", supervisor: "Dr. Winter"> ]
+
It doesn't matter how these objects are retrieved: be it through the
model's own managers/querysets, ForeignKeys, ManyToManyFields
or OneToOneFields.
+``django_polymorphic`` does this only for models that explicitly request this behaviour.
+
The resulting querysets are polymorphic, i.e they may deliver
objects of several different types in a single query result.
-``django_polymorphic`` consists of just one add-on module, ``polymorphic.py``,
-that adds this functionality to Django's model inheritance system
-(for models that request this behaviour).
-
Status
------
-This module is still very experimental. Please see the docs for current restrictions,
-caveats, and performance implications.
+It's important to consider that this code is still very new and
+experimental. Please see the docs for current restrictions, caveats,
+and performance implications.
+
+Right now it's suitable only for the more enterprising early adopters.
+
+It does seem to work well for a number of people (including me), but
+it's still very early and API changes, code reorganisations or further
+schema changes are still a possibility.
+
+
+News
+----
+**2010-1-29:**
+ 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).
+
+ The ``poly`` app - until now being used for test purposes only
+ - has been renamed to ``polymorphic``. See DOCS.rst
+ ("installation/testing") for more info.
+
+**2010-1-26:**
+
+ 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.
View
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+rm /var/tmp/django-polymorphic-test-db.sqlite3
+./manage.py syncdb
+
File renamed without changes.
File renamed without changes.
@@ -5,10 +5,11 @@
from django.core.management.base import NoArgsCommand
from django.db.models import connection
-from poly.models import *
from pprint import pprint
import settings
+from pexp.models import *
+
def reset_queries():
connection.queries=[]
@@ -22,19 +23,19 @@ def handle_noargs(self, **options):
print 'polycmd - sqlite test db is stored in:',settings.DATABASE_NAME
print
+ ModelA.objects.all().delete()
+ o=ModelA.objects.create(field1='A1')
+ o=ModelB.objects.create(field1='B1', field2='B2')
+ o=ModelC.objects.create(field1='C1', field2='C2', field3='C3')
+ print ModelA.objects.all()
+ print
+
Project.objects.all().delete()
o=Project.objects.create(topic="John's gathering")
o=ArtProject.objects.create(topic="Sculpting with Tim", artist="T. Turner")
o=ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
-
print Project.objects.all()
print
-
- ModelA.objects.all().delete()
- o=ModelA.objects.create(field1='A1')
- o=ModelB.objects.create(field1='B1', field2='B2')
- o=ModelC.objects.create(field1='C1', field2='C2', field3='C3')
- print ModelA.objects.all()
View
@@ -0,0 +1,18 @@
+from django.db import models
+
+from polymorphic.models import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet, ShowFields, ShowFieldsAndTypes
+
+
+class Project(ShowFields, 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)
+
+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)
View
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
View
@@ -0,0 +1 @@
+# Create your views here.
@@ -1,11 +0,0 @@
-
-import django
-
-if django.VERSION[:2]==(1,1):
- from polymorphic_dumpdata_11 import Command
-
-elif django.VERSION[:2]==(1,2):
- from polymorphic_dumpdata_12 import Command
-
-else:
- assert False, 'Django version not supported'
Oops, something went wrong.

0 comments on commit 8bdda93

Please sign in to comment.