From 9dda314263eb69fb72fbe410435ee66f01a90c08 Mon Sep 17 00:00:00 2001 From: Jan Seifert Date: Tue, 20 Oct 2020 16:01:30 +0200 Subject: [PATCH] Allow GroupViewSet to be customised (#6477) --- .../customisation/custom_group_viewset.rst | 111 ++++++++++++++++++ docs/advanced_topics/customisation/index.rst | 1 + wagtail/users/apps.py | 1 + .../templates/wagtailusers/groups/create.html | 5 +- .../templates/wagtailusers/groups/edit.html | 5 +- wagtail/users/tests.py | 39 +++++- wagtail/users/wagtail_hooks.py | 28 ++++- 7 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 docs/advanced_topics/customisation/custom_group_viewset.rst diff --git a/docs/advanced_topics/customisation/custom_group_viewset.rst b/docs/advanced_topics/customisation/custom_group_viewset.rst new file mode 100644 index 0000000000..846fd77102 --- /dev/null +++ b/docs/advanced_topics/customisation/custom_group_viewset.rst @@ -0,0 +1,111 @@ +Custom group edit/create page +============================= + +Custom group edit/create page example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This example shows how to customize group 'edit' and 'create' page in Wagtail +admin. + +Let's say you need to connect Active Directory groups with Django groups. +So create a model for Active Directory groups. + +.. code-block:: python + + from django.contrib.auth.models import Group + from django.db import models + + + class ADGroup(models.Model): + guid = models.CharField(verbose_name="GUID", max_length=64, db_index=True, unique=True) + name = models.CharField(verbose_name="Group", max_length=255) + domain = models.CharField(verbose_name="Domain", max_length=255, db_index=True) + description = models.TextField(verbose_name="Description", blank=True, null=True) + roles = models.ManyToManyField(Group, verbose_name="Role", related_name="adgroups", blank=True) + + class Meta: + verbose_name = "AD group" + verbose_name_plural = "AD groups" + +However, there is no role field on the Wagtail group 'edit' or 'create' page. +To add it, inherit from Wagtail group form and add a new field. + +.. code-block:: python + + from django import forms + + from wagtail.users.forms import GroupForm as WagtailGroupForm + + from .models import ADGroup + + + class GroupForm(WagtailGroupForm): + adgroups = forms.ModelMultipleChoiceField( + label="AD groups", + required=False, + queryset=ADGroup.objects.order_by("name"), + ) + + class Meta(WagtailGroupForm.Meta): + fields = WagtailGroupForm.Meta.fields + ("adgroups",) + + def __init__(self, initial=None, instance=None, **kwargs): + if instance is not None: + if initial is None: + initial = {} + initial["adgroups"] = instance.adgroups.all() + super().__init__(initial=initial, instance=instance, **kwargs) + + def save(self, commit=True): + instance = super().save() + instance.adgroups.set(self.cleaned_data["adgroups"]) + return instance + +Now add your custom form into group viewset by inheriting default Wagtail +``GroupViewSet`` class and overriding ``get_form_class`` method. + +.. code-block:: python + + from wagtail.users.views.groups import GroupViewSet as WagtailGroupViewSet + + from .forms import GroupForm + + + class GroupViewSet(WagtailGroupViewSet): + def get_form_class(self, for_update=False): + return GroupForm + +Append the field into group 'edit'/'create' templates. + +.. code-block:: html+Django + + {% extends "wagtailusers/groups/edit.html" %} + {% load wagtailusers_tags wagtailadmin_tags i18n %} + + {% block extra_fields %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.adgroups %} + {% endblock extra_fields %} + +Finally configure ``wagtail.users`` application for using the viewset. Create +``myapplication/apps.py`` module in the main application package and configure +``AppConfig``. + +.. code-block:: python + + from wagtail.users.apps import WagtailUsersAppConfig + + + class CustomUsersAppConfig(WagtailUsersAppConfig): + group_viewset = "myapplication.someapp.viewsets.GroupViewSet" + +And put path to ``CustomUsersAppConfig`` into ``settings.INSTALLED_APPS`` +instead of ``wagtail.users``. + +.. code-block:: python + + INSTALLED_APPS = [ + ..., + "myapplication.apps.CustomUsersAppConfig", + # "wagtail.users", + ..., + ] diff --git a/docs/advanced_topics/customisation/index.rst b/docs/advanced_topics/customisation/index.rst index 94398baf2a..0302ad1601 100644 --- a/docs/advanced_topics/customisation/index.rst +++ b/docs/advanced_topics/customisation/index.rst @@ -11,5 +11,6 @@ Customising Wagtail extending_hallo admin_templates custom_user_models + custom_group_viewset streamfield_blocks custom_account_settings diff --git a/wagtail/users/apps.py b/wagtail/users/apps.py index d6afcc5ad0..5e788cbff5 100644 --- a/wagtail/users/apps.py +++ b/wagtail/users/apps.py @@ -7,3 +7,4 @@ class WagtailUsersAppConfig(AppConfig): label = 'wagtailusers' verbose_name = _("Wagtail users") default_auto_field = 'django.db.models.AutoField' + group_viewset = None diff --git a/wagtail/users/templates/wagtailusers/groups/create.html b/wagtail/users/templates/wagtailusers/groups/create.html index 688b685b23..e79f8e2873 100644 --- a/wagtail/users/templates/wagtailusers/groups/create.html +++ b/wagtail/users/templates/wagtailusers/groups/create.html @@ -20,7 +20,10 @@ {% csrf_token %}