some doc + minor code updates (__repr__ + Show... mixins)
parent
2fcb7fba1a
commit
2795f7acd5
40
DOCS.rst
40
DOCS.rst
|
|
@ -7,18 +7,18 @@ Installation / Testing
|
||||||
Requirements
|
Requirements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Django 1.1 (or later) and Python 2.5 (or later). This code has been tested
|
Django 1.1 (or later) and Python 2.5/2.6. 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 beta and Python 2.5.4 / 2.6.4 on Linux.
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
-------
|
-------
|
||||||
|
|
||||||
The repository (or tar file) contains a complete Django project
|
The repository (or tar file) contains a complete Django project
|
||||||
that may be used for tests or experiments.
|
that may be used for tests or experiments (without any installation needed).
|
||||||
|
|
||||||
To run the included test suite, execute::
|
To run the included test suite, execute::
|
||||||
|
|
||||||
./manage test polymorphic
|
./manage test
|
||||||
|
|
||||||
The management command ``pcmd.py`` in the app ``pexp`` (Polymorphic EXPerimenting)
|
The management command ``pcmd.py`` in the app ``pexp`` (Polymorphic EXPerimenting)
|
||||||
can be used for experiments - modify this file (pexp/management/commands/pcmd.py)
|
can be used for experiments - modify this file (pexp/management/commands/pcmd.py)
|
||||||
|
|
@ -394,9 +394,9 @@ Restrictions & Caveats
|
||||||
option (fixed in Django 1.2).
|
option (fixed in Django 1.2).
|
||||||
|
|
||||||
* Django 1.1 only - when ContentType is used in models, Django's
|
* Django 1.1 only - when ContentType is used in models, Django's
|
||||||
seralisation or fixtures cannot be used. This issue seems to be
|
seralisation or fixtures cannot be used (all polymorphic models
|
||||||
resolved for Django 1.2 (changeset 11863: Fixed #7052, Added support
|
use ContentType). This issue seems to be resolved for Django 1.2
|
||||||
for natural keys in serialization).
|
(changeset 11863: Fixed #7052, Added support for natural keys in serialization).
|
||||||
|
|
||||||
+ http://code.djangoproject.com/ticket/7052
|
+ http://code.djangoproject.com/ticket/7052
|
||||||
+ 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
|
||||||
|
|
@ -408,7 +408,14 @@ Restrictions & Caveats
|
||||||
This problem is aggravated when trying to enhance models.Model
|
This problem is aggravated when trying to enhance models.Model
|
||||||
by subclassing it instead of modifying Django core (as we do here
|
by subclassing it instead of modifying Django core (as we do here
|
||||||
with PolymorphicModel).
|
with PolymorphicModel).
|
||||||
|
|
||||||
|
* It must be possible to instantiate the base model objects, even if your
|
||||||
|
application never does this itself. This is needed by the current
|
||||||
|
implementation of polymorphic querysets but (likely) also by Django internals.
|
||||||
|
Example: If ModelB and ModelC inherit from ModelA, and you never create
|
||||||
|
ModelA objects, django_polymorphic and Django core will still instantiate
|
||||||
|
ModelA objects for temporary purposes (and fail, if this isn't possible).
|
||||||
|
|
||||||
* A reference (``ContentType``) to the real/leaf model is stored
|
* A reference (``ContentType``) to the real/leaf model is stored
|
||||||
in the base model (the base model directly inheriting from
|
in the base model (the base model directly inheriting from
|
||||||
PolymorphicModel). If a model or an app is renamed, then Django's
|
PolymorphicModel). If a model or an app is renamed, then Django's
|
||||||
|
|
@ -428,17 +435,16 @@ Restrictions & Caveats
|
||||||
in PolymorphicModel, which causes some overhead. A minor patch to
|
in PolymorphicModel, which causes some overhead. A minor patch to
|
||||||
Django core would probably get rid of that.
|
Django core would probably get rid of that.
|
||||||
|
|
||||||
|
|
||||||
Project Status
|
Project Status
|
||||||
--------------
|
==============
|
||||||
|
|
||||||
It's important to consider that this code is very new and
|
It's important to consider that this code is very new and
|
||||||
to some extent still experimental. Please see the docs for
|
to some extent still experimental. It does seem to work very
|
||||||
current restrictions, caveats, and performance implications.
|
well for a number of people, but API changes, code reorganisations
|
||||||
|
or further schema changes are still a possibility. There may also
|
||||||
It does seem to work very well for a number of people, but
|
remain larger bugs and problems in the code that have not yet
|
||||||
API changes, code reorganisations or further schema changes
|
been found.
|
||||||
are still a possibility. There may also remain larger bugs
|
|
||||||
and problems in the code that have not yet been found.
|
|
||||||
|
|
||||||
|
|
||||||
Links
|
Links
|
||||||
|
|
|
||||||
31
README.rst
31
README.rst
|
|
@ -2,11 +2,15 @@ Release Notes, Usage, Code
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
* Please see `here for release notes, news and discussion`_ (Google Group)
|
* Please see `here for release notes, news and discussion`_ (Google Group)
|
||||||
* Installation and usage: `Documentation and Examples`_ (or the short `Overview`_)
|
* `Many Examples`_, or full `Installation and Usage Docs`_ (or the short `Overview`_)
|
||||||
* The code is on GitHub_ and Bitbucket_ and can also be downloaded as TGZ_ or ZIP_
|
* Download from GitHub_ or Bitbucket_, or as TGZ_ or ZIP_
|
||||||
|
* Improve django_polymorphic: Report issues, discuss, post patch, or fork the code (GitHub_, Bitbucket_, Newsgroup_, Mail_)
|
||||||
|
|
||||||
.. _here for release notes, news and discussion: http://groups.google.de/group/django-polymorphic/topics
|
.. _here for release notes, news and discussion: http://groups.google.de/group/django-polymorphic/topics
|
||||||
.. _Documentation and Examples: http://bserve.webhop.org/wiki/django_polymorphic/doc
|
.. _Newsgroup: http://groups.google.de/group/django-polymorphic/topics
|
||||||
|
.. _Mail: http://github.com/bconstantin/django_polymorphic/tree/master/setup.py
|
||||||
|
.. _Installation and Usage Docs: http://bserve.webhop.org/wiki/django_polymorphic/doc
|
||||||
|
.. _Many Examples: http://bserve.webhop.org/wiki/django_polymorphic/doc#defining-polymorphic-models
|
||||||
.. _GitHub: http://github.com/bconstantin/django_polymorphic
|
.. _GitHub: http://github.com/bconstantin/django_polymorphic
|
||||||
.. _Bitbucket: http://bitbucket.org/bconstantin/django_polymorphic
|
.. _Bitbucket: http://bitbucket.org/bconstantin/django_polymorphic
|
||||||
.. _TGZ: http://github.com/bconstantin/django_polymorphic/tarball/master
|
.. _TGZ: http://github.com/bconstantin/django_polymorphic/tarball/master
|
||||||
|
|
@ -17,14 +21,8 @@ Release Notes, Usage, Code
|
||||||
What is django_polymorphic good for?
|
What is django_polymorphic good for?
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
It implements seamless polymorphic inheritance for Django models.
|
**Example**: If we define the model ``Project`` as the base class for
|
||||||
|
our models ``ArtProject`` and ``ResearchProject``, and we store one of
|
||||||
This means: objects being retrieved from the database are always returned
|
|
||||||
back with the same type/class and fields they were created and saved with.
|
|
||||||
|
|
||||||
An example:
|
|
||||||
If we defined the model ``Project`` as a base class for our models
|
|
||||||
``ArtProject`` and ``ResearchProject``, and we have stored one of
|
|
||||||
each into the database, then we can do::
|
each into the database, then we can do::
|
||||||
|
|
||||||
>>> Project.objects.all()
|
>>> Project.objects.all()
|
||||||
|
|
@ -32,7 +30,12 @@ each into the database, then we can do::
|
||||||
[ <Project: id 1, topic: "John's Gathering">,
|
[ <Project: id 1, topic: "John's Gathering">,
|
||||||
<ArtProject: id 2, topic: "Sculpting with Tim", artist: "T. Turner">,
|
<ArtProject: id 2, topic: "Sculpting with Tim", artist: "T. Turner">,
|
||||||
<ResearchProject: id 3, topic: "Swallow Aerodynamics", supervisor: "Dr. Winter"> ]
|
<ResearchProject: id 3, topic: "Swallow Aerodynamics", supervisor: "Dr. Winter"> ]
|
||||||
|
|
||||||
|
In general: django_polymorphic implements seamless polymorphic inheritance for Django models.
|
||||||
|
|
||||||
|
The effect: objects are always returned back from the database just
|
||||||
|
as you created them, with the same type/class and fields.
|
||||||
|
|
||||||
It doesn't matter how these objects are retrieved: be it through the
|
It doesn't matter how these objects are retrieved: be it through the
|
||||||
model's own managers/querysets, ForeignKeys, ManyToManyFields
|
model's own managers/querysets, ForeignKeys, ManyToManyFields
|
||||||
or OneToOneFields.
|
or OneToOneFields.
|
||||||
|
|
@ -45,8 +48,10 @@ django_polymorphic does this only for models that explicitely enable it
|
||||||
(and for their submodels).
|
(and for their submodels).
|
||||||
|
|
||||||
Please see the `Documentation and Examples`_ for more information
|
Please see the `Documentation and Examples`_ for more information
|
||||||
(also included as the file ``DOCS.rst`` with the source).
|
or directly look at `more Examples`_.
|
||||||
|
|
||||||
|
.. _Documentation and Examples: http://bserve.webhop.org/wiki/django_polymorphic/doc
|
||||||
|
.. _more Examples: http://bserve.webhop.org/wiki/django_polymorphic/doc#defining-polymorphic-models
|
||||||
|
|
||||||
Status
|
Status
|
||||||
------
|
------
|
||||||
|
|
|
||||||
|
|
@ -710,42 +710,39 @@ class PolymorphicModel(models.Model):
|
||||||
super(PolymorphicModel, self).__init__(*args, **kwargs)
|
super(PolymorphicModel, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
out = self.__class__.__name__ + ': id %d, ' % (self.pk or - 1); last = self._meta.fields[-1]
|
out = self.__class__.__name__ + ': id %d' % (self.pk or - 1)
|
||||||
for f in self._meta.fields:
|
for f in self._meta.fields:
|
||||||
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
||||||
out += f.name + ' (' + type(f).__name__ + ')'
|
out += ', ' + f.name + ' (' + type(f).__name__ + ')'
|
||||||
if f != last: out += ', '
|
|
||||||
return '<' + out + '>'
|
return '<' + out + '>'
|
||||||
|
|
||||||
|
|
||||||
class ShowFields(object):
|
class ShowFields(object):
|
||||||
""" model mixin that shows the object's class, it's fields and field contents """
|
""" model mixin that shows the object's class, it's fields and field contents """
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
out = 'id %d, ' % (self.pk); last = self._meta.fields[-1]
|
out = 'id %d, ' % (self.pk)
|
||||||
for f in self._meta.fields:
|
for f in self._meta.fields:
|
||||||
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
||||||
out += f.name
|
out += ', ' + f.name
|
||||||
if isinstance(f, (models.ForeignKey)):
|
if isinstance(f, (models.ForeignKey)):
|
||||||
o = getattr(self, f.name)
|
o = getattr(self, f.name)
|
||||||
out += ': "' + ('None' if o == None else o.__class__.__name__) + '"'
|
out += ': "' + ('None' if o == None else o.__class__.__name__) + '"'
|
||||||
else:
|
else:
|
||||||
out += ': "' + getattr(self, f.name) + '"'
|
out += ': "' + getattr(self, f.name) + '"'
|
||||||
if f != last: out += ', '
|
|
||||||
return '<' + (self.__class__.__name__ + ': ') + out + '>'
|
return '<' + (self.__class__.__name__ + ': ') + out + '>'
|
||||||
|
|
||||||
|
|
||||||
class ShowFieldsAndTypes(object):
|
class ShowFieldsAndTypes(object):
|
||||||
""" model mixin, like ShowFields, but also show field types """
|
""" model mixin, like ShowFields, but also show field types """
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
out = 'id %d, ' % (self.pk); last = self._meta.fields[-1]
|
out = 'id %d' % (self.pk)
|
||||||
for f in self._meta.fields:
|
for f in self._meta.fields:
|
||||||
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
||||||
out += f.name + ' (' + type(f).__name__ + ')'
|
out += ', ' + f.name + ' (' + type(f).__name__ + ')'
|
||||||
if isinstance(f, (models.ForeignKey)):
|
if isinstance(f, (models.ForeignKey)):
|
||||||
o = getattr(self, f.name)
|
o = getattr(self, f.name)
|
||||||
out += ': "' + ('None' if o == None else o.__class__.__name__) + '"'
|
out += ': "' + ('None' if o == None else o.__class__.__name__) + '"'
|
||||||
else:
|
else:
|
||||||
out += ': "' + getattr(self, f.name) + '"'
|
out += ': "' + getattr(self, f.name) + '"'
|
||||||
if f != last: out += ', '
|
|
||||||
return '<' + self.__class__.__name__ + ': ' + out + '>'
|
return '<' + self.__class__.__name__ + ': ' + out + '>'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,9 @@ class testclass(TestCase):
|
||||||
|
|
||||||
# test ordering
|
# test ordering
|
||||||
expected = '''
|
expected = '''
|
||||||
[ <BlogB: id 4, name (CharField): "Bb3", >,
|
[ <BlogB: id 4, name (CharField): "Bb3">,
|
||||||
<BlogB: id 3, name (CharField): "Bb2", >,
|
<BlogB: id 3, name (CharField): "Bb2">,
|
||||||
<BlogB: id 2, name (CharField): "Bb1", >,
|
<BlogB: id 2, name (CharField): "Bb1">,
|
||||||
<BlogA: id 8, name (CharField): "B5", info (CharField): "i5">,
|
<BlogA: id 8, name (CharField): "B5", info (CharField): "i5">,
|
||||||
<BlogA: id 7, name (CharField): "B4", info (CharField): "i4">,
|
<BlogA: id 7, name (CharField): "B4", info (CharField): "i4">,
|
||||||
<BlogA: id 6, name (CharField): "B3", info (CharField): "i3">,
|
<BlogA: id 6, name (CharField): "B3", info (CharField): "i3">,
|
||||||
|
|
@ -163,9 +163,9 @@ class testclass(TestCase):
|
||||||
<BlogA: id 6, name (CharField): "B3", info (CharField): "i3">,
|
<BlogA: id 6, name (CharField): "B3", info (CharField): "i3">,
|
||||||
<BlogA: id 5, name (CharField): "B2", info (CharField): "i2">,
|
<BlogA: id 5, name (CharField): "B2", info (CharField): "i2">,
|
||||||
<BlogA: id 1, name (CharField): "B1", info (CharField): "i1">,
|
<BlogA: id 1, name (CharField): "B1", info (CharField): "i1">,
|
||||||
<BlogB: id 2, name (CharField): "Bb1", >,
|
<BlogB: id 2, name (CharField): "Bb1">,
|
||||||
<BlogB: id 3, name (CharField): "Bb2", >,
|
<BlogB: id 3, name (CharField): "Bb2">,
|
||||||
<BlogB: id 4, name (CharField): "Bb3", > ]'''
|
<BlogB: id 4, name (CharField): "Bb3"> ]'''
|
||||||
x = '\n' + repr(BlogBase.objects.order_by('-BlogA___info'))
|
x = '\n' + repr(BlogBase.objects.order_by('-BlogA___info'))
|
||||||
assert x == expected
|
assert x == expected
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue