1Third-party applications support 2================================ 3 4 5django-guardian support 6----------------------- 7 8.. versionadded:: 1.0.2 9 10You can configure django-guardian_ to use the base model for object level permissions. 11Add this option to your settings: 12 13.. code-block:: python 14 15 GUARDIAN_GET_CONTENT_TYPE = 'polymorphic.contrib.guardian.get_polymorphic_base_content_type' 16 17This option requires django-guardian_ >= 1.4.6. Details about how this option works are available in the 18`django-guardian documentation <https://django-guardian.readthedocs.io/en/latest/configuration.html#guardian-get-content-type>`_. 19 20 21django-rest-framework support 22----------------------------- 23 24The django-rest-polymorphic_ package provides polymorphic serializers that help you integrate your polymorphic models with `django-rest-framework`. 25 26 27Example 28~~~~~~~ 29 30Define serializers: 31 32.. code-block:: python 33 34 from rest_framework import serializers 35 from rest_polymorphic.serializers import PolymorphicSerializer 36 from .models import Project, ArtProject, ResearchProject 37 38 39 class ProjectSerializer(serializers.ModelSerializer): 40 class Meta: 41 model = Project 42 fields = ('topic', ) 43 44 45 class ArtProjectSerializer(serializers.ModelSerializer): 46 class Meta: 47 model = ArtProject 48 fields = ('topic', 'artist') 49 50 51 class ResearchProjectSerializer(serializers.ModelSerializer): 52 class Meta: 53 model = ResearchProject 54 fields = ('topic', 'supervisor') 55 56 57 class ProjectPolymorphicSerializer(PolymorphicSerializer): 58 model_serializer_mapping = { 59 Project: ProjectSerializer, 60 ArtProject: ArtProjectSerializer, 61 ResearchProject: ResearchProjectSerializer 62 } 63 64Create viewset with serializer_class equals to your polymorphic serializer: 65 66.. code-block:: python 67 68 from rest_framework import viewsets 69 from .models import Project 70 from .serializers import ProjectPolymorphicSerializer 71 72 73 class ProjectViewSet(viewsets.ModelViewSet): 74 queryset = Project.objects.all() 75 serializer_class = ProjectPolymorphicSerializer 76 77 78django-extra-views 79------------------ 80 81.. versionadded:: 1.1 82 83The :mod:`polymorphic.contrib.extra_views` package provides classes to display polymorphic formsets 84using the classes from django-extra-views_. See the documentation of: 85 86* :class:`~polymorphic.contrib.extra_views.PolymorphicFormSetView` 87* :class:`~polymorphic.contrib.extra_views.PolymorphicInlineFormSetView` 88* :class:`~polymorphic.contrib.extra_views.PolymorphicInlineFormSet` 89 90 91django-mptt support 92------------------- 93 94Combining polymorphic with django-mptt_ is certainly possible, but not straightforward. 95It involves combining both managers, querysets, models, meta-classes and admin classes 96using multiple inheritance. 97 98The django-polymorphic-tree_ package provides this out of the box. 99 100 101django-reversion support 102------------------------ 103 104Support for django-reversion_ works as expected with polymorphic models. 105However, they require more setup than standard models. That's become: 106 107* Manually register the child models with django-reversion_, so their ``follow`` parameter can be set. 108* Polymorphic models use `multi-table inheritance <https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance>`_. 109 See the `reversion documentation <https://django-reversion.readthedocs.io/en/latest/api.html#multi-table-inheritance>`_ 110 how to deal with this by adding a ``follow`` field for the primary key. 111* Both admin classes redefine ``object_history_template``. 112 113 114Example 115~~~~~~~ 116 117The admin :ref:`admin example <admin-example>` becomes: 118 119.. code-block:: python 120 121 from django.contrib import admin 122 from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin 123 from reversion.admin import VersionAdmin 124 from reversion import revisions 125 from .models import ModelA, ModelB, ModelC 126 127 128 class ModelAChildAdmin(PolymorphicChildModelAdmin, VersionAdmin): 129 base_model = ModelA # optional, explicitly set here. 130 base_form = ... 131 base_fieldsets = ( 132 ... 133 ) 134 135 class ModelBAdmin(ModelAChildAdmin, VersionAdmin): 136 # define custom features here 137 138 class ModelCAdmin(ModelBAdmin): 139 # define custom features here 140 141 142 class ModelAParentAdmin(VersionAdmin, PolymorphicParentModelAdmin): 143 base_model = ModelA # optional, explicitly set here. 144 child_models = ( 145 (ModelB, ModelBAdmin), 146 (ModelC, ModelCAdmin), 147 ) 148 149 revisions.register(ModelB, follow=['modela_ptr']) 150 revisions.register(ModelC, follow=['modelb_ptr']) 151 admin.site.register(ModelA, ModelAParentAdmin) 152 153Redefine a :file:`admin/polymorphic/object_history.html` template, so it combines both worlds: 154 155.. code-block:: html+django 156 157 {% extends 'reversion/object_history.html' %} 158 {% load polymorphic_admin_tags %} 159 160 {% block breadcrumbs %} 161 {% breadcrumb_scope base_opts %}{{ block.super }}{% endbreadcrumb_scope %} 162 {% endblock %} 163 164This makes sure both the reversion template is used, and the breadcrumb is corrected for the polymorphic model. 165 166.. _django-reversion-compare-support: 167 168django-reversion-compare support 169-------------------------------- 170 171The django-reversion-compare_ views work as expected, the admin requires a little tweak. 172In your parent admin, include the following method: 173 174.. code-block:: python 175 176 def compare_view(self, request, object_id, extra_context=None): 177 """Redirect the reversion-compare view to the child admin.""" 178 real_admin = self._get_real_admin(object_id) 179 return real_admin.compare_view(request, object_id, extra_context=extra_context) 180 181As the compare view resolves the the parent admin, it uses it's base model to find revisions. 182This doesn't work, since it needs to look for revisions of the child model. Using this tweak, 183the view of the actual child model is used, similar to the way the regular change and delete views are redirected. 184 185 186.. _django-extra-views: https://github.com/AndrewIngram/django-extra-views 187.. _django-guardian: https://github.com/django-guardian/django-guardian 188.. _django-mptt: https://github.com/django-mptt/django-mptt 189.. _django-polymorphic-tree: https://github.com/django-polymorphic/django-polymorphic-tree 190.. _django-rest-polymorphic: https://github.com/apirobot/django-rest-polymorphic 191.. _django-reversion-compare: https://github.com/jedie/django-reversion-compare 192.. _django-reversion: https://github.com/etianen/django-reversion 193