[Python-modules-commits] [django-polymorphic] 03/14: Import django-polymorphic_1.0.orig.tar.gz

Michael Fladischer fladi at moszumanska.debian.org
Sun Sep 4 07:30:00 UTC 2016


This is an automated email from the git hooks/post-receive script.

fladi pushed a commit to branch master
in repository django-polymorphic.

commit 93943378499436b2ade3fde81454ae4a38490adb
Author: Michael Fladischer <FladischerMichael at fladi.at>
Date:   Sat Sep 3 21:55:51 2016 +0200

    Import django-polymorphic_1.0.orig.tar.gz
---
 .travis.yml                                        |  67 ++--
 MANIFEST.in                                        |   3 +-
 README.rst                                         |  27 +-
 docs/admin.rst                                     | 232 ++++++++++---
 docs/changelog.rst                                 |  32 +-
 docs/conf.py                                       |   4 +-
 docs/contributing.rst                              |   2 +-
 docs/formsets.rst                                  |  44 +++
 docs/index.rst                                     |  19 +-
 docs/third-party.rst                               |  30 +-
 example/example/settings.py                        |   1 +
 example/orders/__init__.py                         |   0
 example/orders/admin.py                            |  43 +++
 example/orders/migrations/0001_initial.py          |  88 +++++
 example/orders/migrations/__init__.py              |   0
 example/orders/models.py                           |  78 +++++
 example/pexp/admin.py                              |  74 ++---
 example/pexp/management/commands/p2cmd.py          |  58 ++--
 example/pexp/management/commands/pcmd.py           |  19 +-
 example/pexp/management/commands/polybench.py      |   7 +-
 .../commands/polymorphic_create_test_data.py       |  14 -
 example/pexp/migrations/0001_initial.py            | 124 +++----
 example/pexp/migrations/0002_modelc_field4.py      |  20 --
 example/pexp/models.py                             |  69 ++--
 polymorphic/__init__.py                            |   2 +-
 polymorphic/admin/__init__.py                      |  46 +++
 polymorphic/admin/childadmin.py                    | 194 +++++++++++
 polymorphic/admin/filters.py                       |  35 ++
 polymorphic/admin/forms.py                         |  18 +
 polymorphic/admin/generic.py                       |  61 ++++
 polymorphic/admin/helpers.py                       | 139 ++++++++
 polymorphic/admin/inlines.py                       | 248 ++++++++++++++
 polymorphic/{admin.py => admin/parentadmin.py}     | 267 +++------------
 polymorphic/base.py                                | 180 +++++-----
 polymorphic/formsets/__init__.py                   |  53 +++
 polymorphic/formsets/generic.py                    | 112 +++++++
 polymorphic/formsets/models.py                     | 369 +++++++++++++++++++++
 polymorphic/formsets/utils.py                      |  10 +
 polymorphic/managers.py                            |  16 +-
 polymorphic/models.py                              |  16 +-
 polymorphic/query.py                               |  16 +-
 polymorphic/query_translate.py                     |  37 ++-
 polymorphic/showfields.py                          |  28 +-
 .../static/polymorphic/css/polymorphic_inlines.css |  32 ++
 .../static/polymorphic/js/polymorphic_inlines.js   | 334 +++++++++++++++++++
 .../admin/polymorphic/edit_inline/stacked.html     |  36 ++
 polymorphic/tests.py                               | 238 ++++++++++---
 runtests.py                                        |  63 +++-
 setup.py                                           |  14 +-
 tox.ini                                            |   7 +-
 50 files changed, 2836 insertions(+), 790 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index e247041..8f1b076 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,6 @@
+sudo: false
 language: python
+cache: pip
 python:
   - "2.6"
   - "2.7"
@@ -7,56 +9,75 @@ python:
   - "3.4"
   - "3.5"
 env:
-  - DJANGO=">=1.4,<1.5"
-  - DJANGO=">=1.5,<1.6"
-  - DJANGO=">=1.6,<1.7"
-  - DJANGO=">=1.7,<1.8"
-  - DJANGO=">=1.8,<1.9"
-  - DJANGO=">=1.9,<1.10"
+  - DJANGO="Django>=1.4,<1.5"
+  - DJANGO="Django>=1.5,<1.6"
+  - DJANGO="Django>=1.6,<1.7"
+  - DJANGO="Django>=1.7,<1.8"
+  - DJANGO="Django>=1.8,<1.9"
+  - DJANGO="Django>=1.9,<1.10"
+  - DJANGO="Django>=1.10,<1.11"
+  - DJANGO="https://github.com/django/django/tarball/master"
 
 matrix:
   exclude:
   - python: "3.5"
-    env: DJANGO=">=1.4,<1.5"
+    env: DJANGO="Django>=1.4,<1.5"
   - python: "3.5"
-    env: DJANGO=">=1.5,<1.6"
+    env: DJANGO="Django>=1.5,<1.6"
   - python: "3.5"
-    env: DJANGO=">=1.6,<1.7"
+    env: DJANGO="Django>=1.6,<1.7"
   - python: "3.5"
-    env: DJANGO=">=1.7,<1.8"
+    env: DJANGO="Django>=1.7,<1.8"
 
   - python: "3.4"
-    env: DJANGO=">=1.4,<1.5"
+    env: DJANGO="Django>=1.4,<1.5"
   - python: "3.4"
-    env: DJANGO=">=1.9,<1.10"
+    env: DJANGO="Django>=1.9,<1.10"
+  - python: "3.4"
+    env: DJANGO="Django>=1.10,<1.11"
 
   - python: "3.3"
-    env: DJANGO=">=1.4,<1.5"
+    env: DJANGO="Django>=1.4,<1.5"
+  - python: "3.3"
+    env: DJANGO="Django>=1.9,<1.10"
   - python: "3.3"
-    env: DJANGO=">=1.9,<1.10"
+    env: DJANGO="Django>=1.10,<1.11"
+  - python: "3.3"
+    env: DJANGO="https://github.com/django/django/tarball/master"
 
   - python: "3.2"
-    env: DJANGO=">=1.4,<1.5"
+    env: DJANGO="Django>=1.4,<1.5"
+  - python: "3.2"
+    env: DJANGO="Django>=1.9,<1.10"
   - python: "3.2"
-    env: DJANGO=">=1.9,<1.10"
+    env: DJANGO="Django>=1.10,<1.11"
+  - python: "3.2"
+    env: DJANGO="https://github.com/django/django/tarball/master"
 
   - python: "2.6"
-    env: DJANGO=">=1.7,<1.8"
+    env: DJANGO="Django>=1.7,<1.8"
+  - python: "2.6"
+    env: DJANGO="Django>=1.8,<1.9"
   - python: "2.6"
-    env: DJANGO=">=1.8,<1.9"
+    env: DJANGO="Django>=1.9,<1.10"
   - python: "2.6"
-    env: DJANGO=">=1.9,<1.10"
+    env: DJANGO="Django>=1.10,<1.11"
+  - python: "2.6"
+    env: DJANGO="https://github.com/django/django/tarball/master"
+  allow_failures:
+    - env: DJANGO="https://github.com/django/django/tarball/master"
+
+before_install:
+- pip install codecov
 
 install:
-  - pip install django$DJANGO coverage==3.6
+  - pip install -q $DJANGO coverage==3.6
 
 script:
   - coverage run --source=polymorphic runtests.py
-  - coverage report -m
 
 after_success:
-  - pip install coveralls==0.2
-  - coveralls
+- codecov
 
 branches:
   only:
diff --git a/MANIFEST.in b/MANIFEST.in
index 25899f9..aaeedbc 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,4 +2,5 @@ include README.rst
 include LICENSE
 include DOCS.rst
 include CHANGES.rst
-recursive-include polymorphic/templates *
+recursive-include polymorphic/static *.js *.css
+recursive-include polymorphic/templates *.html
diff --git a/README.rst b/README.rst
index c7436c4..52f52af 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,9 @@
-.. image::  https://travis-ci.org/chrisglass/django_polymorphic.png?branch=master
-  :target: http://travis-ci.org/chrisglass/django_polymorphic
-  :alt: build-status
+.. image::  https://travis-ci.org/django-polymorphic/django-polymorphic.png?branch=master
+    :target: http://travis-ci.org/django-polymorphic/django-polymorphic
+.. image:: https://img.shields.io/pypi/v/django-polymorphic-tree.svg
+    :target: https://pypi.python.org/pypi/django-polymorphic-tree/
+.. image:: https://img.shields.io/codecov/c/github/django-polymorphic/django-polymorphic/master.svg
+    :target: https://codecov.io/github/django-polymorphic/django-polymorphic?branch=master
 
 Polymorphic Models for Django
 =============================
@@ -10,20 +13,26 @@ When a query is made at the base model, the inherited model classes are returned
 
 When we store models that inherit from a ``Project`` model...
 
->>> Project.objects.create(topic="Department Party")
->>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner")
->>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
+.. code-block:: python
+
+    >>> Project.objects.create(topic="Department Party")
+    >>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner")
+    >>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
 
 ...and want to retrieve all our projects, the subclassed models are returned!
 
->>> Project.objects.all()
+.. code-block:: python
+
+    >>> Project.objects.all()
     [ <Project:         id 1, topic "Department Party">,
       <ArtProject:      id 2, topic "Painting with Tim", artist "T. Turner">,
       <ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ]
 
 Using vanilla Django, we get the base class objects, which is rarely what we wanted:
 
->>> Project.objects.all()
+.. code-block:: python
+
+    >>> Project.objects.all()
     [ <Project: id 1, topic "Department Party">,
       <Project: id 2, topic "Painting with Tim">,
       <Project: id 3, topic "Swallow Aerodynamics"> ]
@@ -52,7 +61,7 @@ Django to perform an ``INNER JOIN`` to fetch the model fields from the database.
 While taking this in mind, there are valid reasons for using subclassed models.
 That's what this library is designed for!
 
-For more information, see the `documentation at Read the Docs <https://django-polymorphic.readthedocs.org/>`_.
+For more information, see the `documentation at Read the Docs <https://django-polymorphic.readthedocs.io/>`_.
 
 License
 =======
diff --git a/docs/admin.rst b/docs/admin.rst
index 8e499c7..39fc68f 100644
--- a/docs/admin.rst
+++ b/docs/admin.rst
@@ -4,63 +4,48 @@ Django admin integration
 Off course, it's possible to register individual polymorphic models in the Django admin interface.
 However, to use these models in a single cohesive interface, some extra base classes are available.
 
-The polymorphic admin interface works in a simple way:
-
-* The add screen gains an additional step where the desired child model is selected.
-* The edit screen displays the admin interface of the child model.
-* The list screen still displays all objects of the base class.
-
-The polymorphic admin is implemented via a parent admin that forwards the *edit* and *delete* views
-to the ``ModelAdmin`` of the derived child model. The *list* page is still implemented by the parent model admin.
+Setup
+-----
 
 Both the parent model and child model need to have a ``ModelAdmin`` class.
-Only the ``ModelAdmin`` class of the parent/base model has to be registered in the Django admin site.
 
-The parent model
-----------------
+The shared base model should use the :class:`~polymorphic.admin.PolymorphicParentModelAdmin` as base class.
 
-The parent model needs to inherit ``PolymorphicParentModelAdmin``, and implement the following:
+ * :attr:`~polymorphic.admin.PolymorphicParentModelAdmin.base_model` should be set
+ * :attr:`~polymorphic.admin.PolymorphicParentModelAdmin.child_models` or
+   :meth:`~polymorphic.admin.PolymorphicParentModelAdmin.get_child_models` should return an iterable of Model classes.
 
-* ``base_model`` should be set
-* ``child_models`` or ``get_child_models()`` should return a list with (Model, ModelAdmin) tuple.
+The admin class for every child model should inherit from :class:`~polymorphic.admin.PolymorphicChildModelAdmin`
 
-The exact implementation can depend on the way your module is structured.
-For simple inheritance situations, ``child_models`` is the best solution.
-For large applications, ``get_child_models()`` can be used to query a plugin registration system.
+ * :attr:`~polymorphic.admin.PolymorphicChildModelAdmin.base_model` should be set.
 
-By default, the non_polymorphic() method will be called on the queryset, so
-only the Parent model will be provided to the list template.  This is to avoid
-the performance hit of retrieving child models.
-
-This can be controlled by setting the ``polymorphic_list`` property on the
-parent admin.  Setting it to True will provide child models to the list template.
-
-Note: If you are using non-integer primary keys in your model, you have to edit ``pk_regex``, 
-for example ``pk_regex = '([\w-]+)'`` if you use UUIDs. Otherwise you cannot change model entries.
-
-The child models
-----------------
-
-The admin interface of the derived models should inherit from ``PolymorphicChildModelAdmin``.
-Again, ``base_model`` should be set in this class as well.
-This class implements the following features:
+Although the child models are registered too, they won't be shown in the admin index page.
+This only happens when :attr:`~polymorphic.admin.PolymorphicChildModelAdmin.show_in_index` is set to ``True``.
 
-* It corrects the breadcrumbs in the admin pages.
-* It extends the template lookup paths, to look for both the parent model and child model in the ``admin/app/model/change_form.html`` path.
-* It allows to set ``base_form`` so the derived class will automatically include other fields in the form.
-* It allows to set ``base_fieldsets`` so the derived class will automatically display any extra fields.
+Fieldset configuration
+~~~~~~~~~~~~~~~~~~~~~~
 
-The standard ``ModelAdmin`` attributes ``form`` and ``fieldsets`` should rather be avoided at the base class,
-because it will hide any additional fields which are defined in the derived model. Instead,
-use the ``base_form`` and ``base_fieldsets`` instead. The ``PolymorphicChildModelAdmin`` will
-automatically detect the additional fields that the child model has, display those in a separate fieldset.
+The parent admin is only used for the list display of models,
+and for the edit/delete view of non-subclassed models.
 
+All other model types are redirected to the edit/delete/history view of the child model admin.
+Hence, the fieldset configuration should be placed on the child admin.
 
-Polymorphic Inlines
--------------------
+.. tip::
+    When the child admin is used as base class for various derived classes, avoid using
+    the standard ``ModelAdmin`` attributes ``form`` and ``fieldsets``.
+    Instead, use the ``base_form`` and ``base_fieldsets`` attributes.
+    This allows the :class:`~polymorphic.admin.PolymorphicChildModelAdmin` class
+    to detect any additional fields in case the child model is overwritten.
 
-To add a polymorphic child model as an Inline for another model, add a field to the inline's readonly_fields list formed by the lowercased name of the polymorphic parent model with the string "_ptr" appended to it. Otherwise, trying to save that model in the admin will raise an AttributeError with the message "can't set attribute".
+.. versionchanged:: 1.0
+    It's now needed to register the child model classes too.
 
+    In *django-polymorphic* 0.9 and below, the ``child_models`` was a tuple of a ``(Model, ChildModelAdmin)``.
+    The admin classes were registered in an internal class, and kept away from the main admin site.
+    This caused various subtle problems with the ``ManyToManyField`` and related field wrappers,
+    which are fixed by registering the child admin classes too. Note that they are hidden from
+    the main view, unless :attr:`~polymorphic.admin.PolymorphicChildModelAdmin.show_in_index` is set.
 
 .. _admin-example:
 
@@ -72,7 +57,7 @@ The models are taken from :ref:`advanced-features`.
 .. code-block:: python
 
     from django.contrib import admin
-    from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin
+    from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter
     from .models import ModelA, ModelB, ModelC, StandardModel
 
 
@@ -88,35 +73,174 @@ The models are taken from :ref:`advanced-features`.
         )
 
 
+    @admin.register(ModelB)
     class ModelBAdmin(ModelAChildAdmin):
         base_model = ModelB
         # define custom features here
 
 
+    @admin.register(ModelC)
     class ModelCAdmin(ModelBAdmin):
         base_model = ModelC
+        show_in_index = True  # makes child model admin visible in main admin site
         # define custom features here
 
 
+    @admin.register(ModelA)
     class ModelAParentAdmin(PolymorphicParentModelAdmin):
         """ The parent model admin """
         base_model = ModelA
-        child_models = (
-            (ModelB, ModelBAdmin),
-            (ModelC, ModelCAdmin),
+        child_models = (ModelB, ModelC)
+        list_filter = (PolymorphicChildModelFilter,)  # This is optional.
+
+
+
+Filtering child types
+---------------------
+
+Child model types can be filtered by adding a :class:`~polymorphic.admin.PolymorphicChildModelFilter`
+to the ``list_filter`` attribute. See the example above.
+
+
+Inline models
+-------------
+
+.. versionadded:: 1.0
+
+Inline models are handled via a special :class:`~polymorphic.admin.StackedPolymorphicInline` class.
+
+For models with a generic foreign key, there is a :class:`~polymorphic.admin.GenericStackedPolymorphicInline` class available.
+
+When the inline is included to a normal :class:`~django.contrib.admin.ModelAdmin`,
+make sure the :class:`~polymorphic.admin.PolymorphicInlineSupportMixin` is included.
+This is not needed when the admin inherits from the
+:class:`~polymorphic.admin.PolymorphicParentModelAdmin` /
+:class:`~polymorphic.admin.PolymorphicChildModelAdmin` classes.
+
+In the following example, the ``PaymentInline`` supports several types.
+These are defined as separate inline classes.
+The child classes can be nested for clarity, but this is not a requirement.
+
+.. code-block:: python
+
+    from django.contrib import admin
+
+    from polymorphic.admin import PolymorphicInlineSupportMixin, StackedPolymorphicInline
+    from .models import Order, Payment, CreditCardPayment, BankPayment, SepaPayment
+
+
+    class PaymentInline(StackedPolymorphicInline):
+        """
+        An inline for a polymorphic model.
+        The actual form appearance of each row is determined by
+        the child inline that corresponds with the actual model type.
+        """
+        class CreditCardPaymentInline(StackedPolymorphicInline.Child):
+            model = CreditCardPayment
+
+        class BankPaymentInline(StackedPolymorphicInline.Child):
+            model = BankPayment
+
+        class SepaPaymentInline(StackedPolymorphicInline.Child):
+            model = SepaPayment
+
+        model = Payment
+        child_inlines = (
+            CreditCardPaymentInline,
+            BankPaymentInline,
+            SepaPaymentInline,
         )
 
 
+    @admin.register(Order)
+    class OrderAdmin(PolymorphicInlineSupportMixin, admin.ModelAdmin):
+        """
+        Admin for orders.
+        The inline is polymorphic.
+        To make sure the inlines are properly handled,
+        the ``PolymorphicInlineSupportMixin`` is needed to
+        """
+        inlines = (PaymentInline,)
+
+
+
+
+Using polymorphic models in standard inlines
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To add a polymorphic child model as an Inline for another model, add a field to the inline's ``readonly_fields`` list
+formed by the lowercased name of the polymorphic parent model with the string ``_ptr`` appended to it.
+Otherwise, trying to save that model in the admin will raise an AttributeError with the message "can't set attribute".
+
+.. code-block:: python
+
+    from django.contrib import admin
+    from .models import StandardModel
+
+
     class ModelBInline(admin.StackedInline):
         model = ModelB
         fk_name = 'modelb'
         readonly_fields = ['modela_ptr']
-    
-        
+
+
+    @admin.register(StandardModel)
     class StandardModelAdmin(admin.ModelAdmin):
         inlines = [ModelBInline]
-        
 
-    # Only the parent needs to be registered:
-    admin.site.register(ModelA, ModelAParentAdmin)
-    admin.site.register(StandardModel, StandardModelAdmin)
+
+
+Internal details
+----------------
+
+The polymorphic admin interface works in a simple way:
+
+* The add screen gains an additional step where the desired child model is selected.
+* The edit screen displays the admin interface of the child model.
+* The list screen still displays all objects of the base class.
+
+The polymorphic admin is implemented via a parent admin that redirects the *edit* and *delete* views
+to the ``ModelAdmin`` of the derived child model. The *list* page is still implemented by the parent model admin.
+
+The parent model
+~~~~~~~~~~~~~~~~
+
+The parent model needs to inherit :class:`~polymorphic.admin.PolymorphicParentModelAdmin`, and implement the following:
+
+ * :attr:`~polymorphic.admin.PolymorphicParentModelAdmin.base_model` should be set
+ * :attr:`~polymorphic.admin.PolymorphicParentModelAdmin.child_models` or
+   :meth:`~polymorphic.admin.PolymorphicParentModelAdmin.get_child_models` should return an iterable of Model classes.
+
+The exact implementation can depend on the way your module is structured.
+For simple inheritance situations, ``child_models`` is the best solution.
+For large applications, ``get_child_models()`` can be used to query a plugin registration system.
+
+By default, the non_polymorphic() method will be called on the queryset, so
+only the Parent model will be provided to the list template.  This is to avoid
+the performance hit of retrieving child models.
+
+This can be controlled by setting the ``polymorphic_list`` property on the
+parent admin.  Setting it to True will provide child models to the list template.
+
+If you use other applications such as django-reversion_ or django-mptt_, please check +:ref:`third-party`.
+
+Note: If you are using non-integer primary keys in your model, you have to edit ``pk_regex``,
+for example ``pk_regex = '([\w-]+)'`` if you use UUIDs. Otherwise you cannot change model entries.
+
+The child models
+~~~~~~~~~~~~~~~~
+
+The admin interface of the derived models should inherit from :class:`~polymorphic.admin.PolymorphicChildModelAdmin`.
+Again, :attr:`~polymorphic.admin.PolymorphicChildModelAdmin.base_model` should be set in this class as well.
+This class implements the following features:
+
+* It corrects the breadcrumbs in the admin pages.
+* It extends the template lookup paths, to look for both the parent model and child model in the ``admin/app/model/change_form.html`` path.
+* It allows to set :attr:`~polymorphic.admin.PolymorphicChildModelAdmin.base_form` so the derived class will automatically include other fields in the form.
+* It allows to set :attr:`~polymorphic.admin.PolymorphicChildModelAdmin.base_fieldsets` so the derived class will automatically display any extra fields.
+* Although it must be registered with admin site, by default it's hidden from admin site index page.
+  This can be overriden by adding :attr:`~polymorphic.admin.PolymorphicChildModelAdmin.show_in_index` = ``True`` in admin class.
+
+
+.. _django-reversion: https://github.com/etianen/django-reversion
+.. _django-mptt: https://github.com/django-mptt/django-mptt
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 6053688..9d74887 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -1,6 +1,36 @@
 Changelog
 =========
 
+Version 1.0 (2016-09-02)
+------------------------
+
+* Added Django 1.10 support.
+* Added **admin inline** support for polymorphic models.
+* Added **formset** support for polymorphic models.
+* Added support for polymorphic queryset limiting effects on *proxy models*.
+* Added support for multiple databases with the ``.using()`` method and ``using=..`` keyword argument.
+* Fixed modifying passed ``Q()`` objects in place.
+
+.. note::
+   This version provides a new method for registering the admin models.
+   While the old method is still supported, we recommend to upgrade your code.
+   The new registration style improves the compatibility in the Django admin.
+
+   * Register each ``PolymorphicChildModelAdmin`` with the admin site too.
+   * The ``child_models`` attribute of the ``PolymorphicParentModelAdmin`` should be a flat list of all child models.
+     The ``(model, admin)`` tuple is obsolete.
+
+   Also note that proxy models will now limit the queryset too.
+
+
+Fixed since 1.0b1 (2016-08-10)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix formset empty-form display when there are form errors.
+* Fix formset empty-form hiding for Grappelli_.
+* Fixed packing ``admin/polymorphic/edit_inline/stacked.html`` in the wheel format.
+
+
 Version 0.9.2 (2016-05-04)
 --------------------------
 
@@ -219,6 +249,6 @@ It supports Django 1.1 up till 1.4 and Python 2.4 up till 2.7.
 For a detailed list of it's changes, see the :doc:`archived changelog <changelog_archive>`.
 
 .. _Grappelli: http://grappelliproject.com/
-.. _django-parler: https://github.com/edoburu/django-parler
+.. _django-parler: https://github.com/django-parler/django-parler
 .. _django-reversion: https://github.com/etianen/django-reversion
 .. _django-reversion-compare: https://github.com/jedie/django-reversion-compare
diff --git a/docs/conf.py b/docs/conf.py
index 7f84262..6bada59 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -55,9 +55,9 @@ copyright = u'2013, Bert Constantin, Chris Glass, Diederik van der Boor'
 # built documents.
 #
 # The short X.Y version.
-version = '0.9.2'
+version = '1.0'
 # The full version, including alpha/beta/rc tags.
-release = '0.9.2'
+release = '1.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/contributing.rst b/docs/contributing.rst
index d4e99d2..defd99a 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -3,7 +3,7 @@ Contributing
 
 You can contribute to *django-polymorphic* to forking the code on GitHub:
 
-  https://github.com/chrisglass/django_polymorphic
+  https://github.com/django-polymorphic/django-polymorphic
 
 
 Running tests
diff --git a/docs/formsets.rst b/docs/formsets.rst
new file mode 100644
index 0000000..0618433
--- /dev/null
+++ b/docs/formsets.rst
@@ -0,0 +1,44 @@
+Formsets
+========
+
+.. versionadded:: 1.0
+
+Polymorphic models can be used in formsets.
+
+The implementation is almost identical to the regular Django formsets.
+As extra parameter, the factory needs to know how to display the child models.
+Provide a list of :class:`~polymorphic.formsets.PolymorphicFormSetChild` objects for this.
+
+.. code-block:: python
+
+    from polymorphic.formsets import polymorphic_modelformset_factory, PolymorphicFormSetChild
+
+    ModelAFormSet = polymorphic_modelformset_factory(ModelA, formset_children=(
+        PolymorphicFormSetChild(ModelB),
+        PolymorphicFormSetChild(ModelC),
+    ))
+
+The formset can be used just like all other formsets:
+
+.. code-block:: python
+
+    if request.method == "POST":
+        formset = ModelAFormSet(request.POST, request.FILES, queryset=ModelA.objects.all())
+        if formset.is_valid():
+            formset.save()
+    else:
+        formset = ModelAFormSet(queryset=ModelA.objects.all())
+
+Like standard Django formsets, there are 3 factory methods available:
+
+* :func:`~polymorphic.formsets.polymorphic_modelformset_factory` - create a regular model formset.
+* :func:`~polymorphic.formsets.polymorphic_inlineformset_factory` - create a inline model formset.
+* :func:`~polymorphic.formsets.generic_polymorphic_inlineformset_factory` - create an inline formset for a generic foreign key.
+
+Each one uses a different base class:
+
+* :class:`~polymorphic.formsets.BasePolymorphicModelFormSet`
+* :class:`~polymorphic.formsets.BasePolymorphicInlineFormSet`
+* :class:`~polymorphic.formsets.BaseGenericPolymorphicInlineFormSet`
+
+When needed, the base class can be overwritten and provided to the factory via the ``formset`` parameter.
diff --git a/docs/index.rst b/docs/index.rst
index 67b5f69..f648091 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -6,20 +6,26 @@ When a query is made at the base model, the inherited model classes are returned
 
 When we store models that inherit from a ``Project`` model...
 
->>> Project.objects.create(topic="Department Party")
->>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner")
->>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
+.. code-block:: python
+
+    >>> Project.objects.create(topic="Department Party")
+    >>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner")
+    >>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
 
 ...and want to retrieve all our projects, the subclassed models are returned!
 
->>> Project.objects.all()
+.. code-block:: python
+
+    >>> Project.objects.all()
     [ <Project:         id 1, topic "Department Party">,
       <ArtProject:      id 2, topic "Painting with Tim", artist "T. Turner">,
       <ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ]
 
 Using vanilla Django, we get the base class objects, which is rarely what we wanted:
 
->>> Project.objects.all()
+.. code-block:: python
+
+    >>> Project.objects.all()
     [ <Project: id 1, topic "Department Party">,
       <Project: id 2, topic "Painting with Tim">,
       <Project: id 3, topic "Swallow Aerodynamics"> ]
@@ -57,9 +63,10 @@ Advanced topics
 .. toctree::
    :maxdepth: 2
 
+   formsets
    migrating
-   advanced
    managers
+   advanced
    third-party
    changelog
    contributing
diff --git a/docs/third-party.rst b/docs/third-party.rst
index 1bac44b..7b274f5 100644
--- a/docs/third-party.rst
+++ b/docs/third-party.rst
@@ -1,16 +1,26 @@
 Third-party applications support
 ================================
 
+
+django-mptt support
+-------------------
+
+Combining polymorphic with django-mptt_ is certainly possible, but not straightforward.
+It involves combining both managers, querysets, models, meta-classes and admin classes
+using multiple inheritance.
+
+The django-polymorphic-tree_ package provides this out of the box.
+
+
 django-reversion support
 ------------------------
 
 Support for django-reversion_ works as expected with polymorphic models.
 However, they require more setup than standard models. That's become:
 
-* The children models are not registered in the admin site.
-  You will therefore need to manually register them to django-reversion_.
+* Manually register the child models with django-reversion_, so their ``follow`` parameter can be set.
 * Polymorphic models use `multi-table inheritance <https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance>`_.
-  See the `reversion documentation <http://django-reversion.readthedocs.org/en/latest/api.html#multi-table-inheritance>`_
+  See the `reversion documentation <https://django-reversion.readthedocs.io/en/latest/api.html#multi-table-inheritance>`_
   how to deal with this by adding a ``follow`` field for the primary key.
 * Both admin classes redefine ``object_history_template``.
 
@@ -18,7 +28,7 @@ However, they require more setup than standard models. That's become:
 Example
 ~~~~~~~
 
-The admin :ref:`admin-example` becomes:
+The admin :ref:`admin example <admin-example>` becomes:
 
 .. code-block:: python
 
@@ -87,17 +97,7 @@ This doesn't work, since it needs to look for revisions of the child model. Usin
 the view of the actual child model is used, similar to the way the regular change and delete views are redirected.
 
 
-django-mptt support
--------------------
-
-Combining polymorphic with django-mptt_ is certainly possible, but not straightforward.
-It involves combining both managers, querysets, models, meta-classes and admin classes
-using multiple inheritance.
-
-The django-polymorphic-tree_ package provides this out of the box.
-
-
 .. _django-reversion: https://github.com/etianen/django-reversion
 .. _django-reversion-compare: https://github.com/jedie/django-reversion-compare
 .. _django-mptt: https://github.com/django-mptt/django-mptt
-.. _django-polymorphic-tree: https://github.com/edoburu/django-polymorphic-tree
+.. _django-polymorphic-tree: https://github.com/django-polymorphic/django-polymorphic-tree
diff --git a/example/example/settings.py b/example/example/settings.py
index 9e33a05..8679620 100644
--- a/example/example/settings.py
+++ b/example/example/settings.py
@@ -73,6 +73,7 @@ INSTALLED_APPS = (
 
     'polymorphic',      # needed if you want to use the polymorphic admin
     'pexp',             # this Django app is for testing and experimentation; not needed otherwise
+    'orders',
 )
 
 if django.VERSION >= (1, 7):
diff --git a/example/orders/__init__.py b/example/orders/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/example/orders/admin.py b/example/orders/admin.py
new file mode 100644
index 0000000..755c3ad
--- /dev/null
+++ b/example/orders/admin.py
@@ -0,0 +1,43 @@
+from django.contrib import admin
+
+from polymorphic.admin import PolymorphicInlineSupportMixin, StackedPolymorphicInline
+from .models import Order, Payment, CreditCardPayment, BankPayment, SepaPayment
+
+
+class CreditCardPaymentInline(StackedPolymorphicInline.Child):
+    model = CreditCardPayment
+
+
+class BankPaymentInline(StackedPolymorphicInline.Child):
+    model = BankPayment
+
+
+class SepaPaymentInline(StackedPolymorphicInline.Child):
+    model = SepaPayment
+
+
+class PaymentInline(StackedPolymorphicInline):
+    """
+    An inline for a polymorphic model.
+    The actual form appearance of each row is determined by
+    the child inline that corresponds with the actual model type.
+    """
+
+    model = Payment
+    child_inlines = (
+        CreditCardPaymentInline,
+        BankPaymentInline,
+        SepaPaymentInline,
+    )
+
+
+ at admin.register(Order)
+class OrderAdmin(PolymorphicInlineSupportMixin, admin.ModelAdmin):
+    """
+    Admin for orders.
+    The inline is polymorphic.
+    To make sure the inlines are properly handled,
+    the ``PolymorphicInlineSupportMixin`` is needed to
+    """
+    inlines = (PaymentInline,)
+
diff --git a/example/orders/migrations/0001_initial.py b/example/orders/migrations/0001_initial.py
new file mode 100644
index 0000000..f32d754
--- /dev/null
+++ b/example/orders/migrations/0001_initial.py
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('contenttypes', '0002_remove_content_type_name'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Order',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('title', models.CharField(max_length=200, verbose_name='Title')),
+            ],
+            options={
+                'ordering': ('title',),
+                'verbose_name': 'Organisation',
+                'verbose_name_plural': 'Organisations',
+            },
+        ),
+        migrations.CreateModel(
+            name='Payment',
+            fields=[
+                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+                ('currency', models.CharField(default=b'USD', max_length=3)),
+                ('amount', models.DecimalField(max_digits=10, decimal_places=2)),
+            ],
+            options={
+                'verbose_name': 'Payment',
+                'verbose_name_plural': 'Payments',
+            },
+        ),
+        migrations.CreateModel(
+            name='BankPayment',
+            fields=[
+                ('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orders.Payment')),
+                ('bank_name', models.CharField(max_length=100)),
+                ('swift', models.CharField(max_length=20)),
+            ],
+            options={
+                'verbose_name': 'Bank Payment',
+                'verbose_name_plural': 'Bank Payments',
+            },
+            bases=('orders.payment',),
+        ),
+        migrations.CreateModel(
+            name='CreditCardPayment',
+            fields=[
+                ('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orders.Payment')),
+                ('card_type', models.CharField(max_length=10)),
+                ('expiry_month', models.PositiveSmallIntegerField(choices=[(1, 'jan'), (2, 'feb'), (3, 'mar'), (4, 'apr'), (5, 'may'), (6, 'jun'), (7, 'jul'), (8, 'aug'), (9, 'sep'), (10, 'oct'), (11, 'nov'), (12, 'dec')])),
+                ('expiry_year', models.PositiveIntegerField()),
+            ],
+            options={
+                'verbose_name': 'Credit Card Payment',
+                'verbose_name_plural': 'Credit Card Payments',
+            },
+            bases=('orders.payment',),
+        ),
+        migrations.CreateModel(
+            name='SepaPayment',
+            fields=[
+                ('payment_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orders.Payment')),
+                ('iban', models.CharField(max_length=34)),
+                ('bic', models.CharField(max_length=11)),
+            ],
+            options={
+                'verbose_name': 'Bank Payment',
+                'verbose_name_plural': 'Bank Payments',
+            },
+            bases=('orders.payment',),
+        ),
+        migrations.AddField(
+            model_name='payment',
+            name='order',
+            field=models.ForeignKey(to='orders.Order'),
+        ),
+        migrations.AddField(
+            model_name='payment',
+            name='polymorphic_ctype',
+            field=models.ForeignKey(related_name='polymorphic_orders.payment_set+', editable=False, to='contenttypes.ContentType', null=True),
+        ),
+    ]
diff --git a/example/orders/migrations/__init__.py b/example/orders/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/example/orders/models.py b/example/orders/models.py
new file mode 100644
index 0000000..9691fae
--- /dev/null
+++ b/example/orders/models.py
@@ -0,0 +1,78 @@
+from django.db import models
+from django.utils.dates import MONTHS_3
+from django.utils.six import python_2_unicode_compatible
+from django.utils.translation import ugettext_lazy as _
+
+from polymorphic.models import PolymorphicModel
+
+
+ at python_2_unicode_compatible
+class Order(models.Model):
+    """
+    An example order that has polymorphic relations
+    """
+    title = models.CharField(_("Title"), max_length=200)
+
+    class Meta:
+        verbose_name = _("Organisation")
+        verbose_name_plural = _("Organisations")
+        ordering = ('title',)
+
+    def __str__(self):
+        return self.title
+
+
+ at python_2_unicode_compatible
+class Payment(PolymorphicModel):
+    """
+    A generic payment model.
+    """
+    order = models.ForeignKey(Order)
+    currency = models.CharField(default='USD', max_length=3)
+    amount = models.DecimalField(max_digits=10, decimal_places=2)
+
+    class Meta:
+        verbose_name = _("Payment")
+        verbose_name_plural = _("Payments")
+
+    def __str__(self):
+        return "{0} {1}".format(self.currency, self.amount)
+
+
+class CreditCardPayment(Payment):
+    """
+    Credit card
+    """
+    MONTH_CHOICES = [(i, n) for i, n in sorted(MONTHS_3.items())]
+
+    card_type = models.CharField(max_length=10)
+    expiry_month = models.PositiveSmallIntegerField(choices=MONTH_CHOICES)
+    expiry_year = models.PositiveIntegerField()
+
+    class Meta:
+        verbose_name = _("Credit Card Payment")
+        verbose_name_plural = _("Credit Card Payments")
+
+
+class BankPayment(Payment):
+    """
+    Payment by bank
+    """
+    bank_name = models.CharField(max_length=100)
+    swift = models.CharField(max_length=20)
+
+    class Meta:
+        verbose_name = _("Bank Payment")
+        verbose_name_plural = _("Bank Payments")
+
+
... 3996 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-polymorphic.git



More information about the Python-modules-commits mailing list