From 449a48d7f9816fa17eda2ca258de41ed13df8e39 Mon Sep 17 00:00:00 2001 From: Sage Abdullah <sage.abdullah@torchbox.com> Date: Tue, 2 Jul 2024 14:58:51 +0100 Subject: [PATCH] Reorganise docs for custom user forms to prefer UserViewSet customisation And make small tweaks to the GroupViewSet docs so the custom apps examples align. --- .../customisation/custom_user_models.md | 74 ++++++++++++------- docs/extending/customizing_group_views.md | 14 +++- docs/reference/settings.md | 2 + 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/docs/advanced_topics/customisation/custom_user_models.md b/docs/advanced_topics/customisation/custom_user_models.md index 76fe06b758..8d264b701d 100644 --- a/docs/advanced_topics/customisation/custom_user_models.md +++ b/docs/advanced_topics/customisation/custom_user_models.md @@ -1,13 +1,15 @@ # Custom user models -## Custom user forms example +This page shows how to configure Wagtail to accommodate a custom user model. -This example shows how to add a text field and foreign key field to a custom user model -and configure Wagtail user forms to allow the fields values to be updated. +## Creating a custom user model -Create a custom user model. This must at minimum inherit from `AbstractBaseUser` and `PermissionsMixin`. In this case, we extend the `AbstractUser` class and add two fields. The foreign key references another model (not shown). +This example uses a custom user model that adds a text field and foreign key field. + +The custom user model must at minimum inherit from {class}`~django.contrib.auth.models.AbstractBaseUser` and {class}`~django.contrib.auth.models.PermissionsMixin`. In this case, we extend the {class}`~django.contrib.auth.models.AbstractUser` class and add two fields. The foreign key references another model (not shown). ```python +# myapp/models.py from django.contrib.auth.models import AbstractUser class User(AbstractUser): @@ -17,21 +19,25 @@ class User(AbstractUser): Add the app containing your user model to `INSTALLED_APPS` - it must be above the `'wagtail.users'` line, in order to override Wagtail's built-in templates - and set [AUTH_USER_MODEL](https://docs.djangoproject.com/en/stable/topics/auth/customizing/#substituting-a-custom-user-model) to reference -your model. In this example the app is called `users` and the model is `User` +your model. In this example the app is called `myapp` and the model is `User`. ```python -AUTH_USER_MODEL = 'users.User' +AUTH_USER_MODEL = 'myapp.User' ``` +## Creating custom user forms + +Now we need to configure Wagtail's user forms to allow the custom fields' values to be updated. Create your custom user 'create' and 'edit' forms in your app: ```python +# myapp/forms.py from django import forms from django.utils.translation import gettext_lazy as _ from wagtail.users.forms import UserEditForm, UserCreationForm -from users.models import MembershipStatus +from myapp.models import MembershipStatus class CustomUserEditForm(UserEditForm): @@ -44,8 +50,11 @@ class CustomUserCreationForm(UserCreationForm): status = forms.ModelChoiceField(queryset=MembershipStatus.objects, required=True, label=_("Status")) ``` +## Extending the create and edit templates + Extend the Wagtail user 'create' and 'edit' templates. These extended templates should be placed in a template directory `wagtailusers/users`. +Using a custom template directory is possible and will be explained later. Template create.html: @@ -70,29 +79,22 @@ Template edit.html: ``` The `extra_fields` block allows fields to be inserted below the `last_name` field -in the default templates. Other block-overriding options exist to allow appending +in the default templates. There is a `fields` block that allows appending fields to the end or beginning of the existing fields or to allow all the fields to be redefined. -Add the Wagtail settings to your project to reference the user form additions: - -```python -WAGTAIL_USER_EDIT_FORM = 'users.forms.CustomUserEditForm' -WAGTAIL_USER_CREATION_FORM = 'users.forms.CustomUserCreationForm' -WAGTAIL_USER_CUSTOM_FIELDS = ['country', 'status'] -``` - -```{versionadded} 6.2 -The ability to customize the `UserViewSet` was added. Instead of customizing the forms via the `WAGTAIL_USER_EDIT_FORM`, `WAGTAIL_USER_CREATION_FORM`, and `WAGTAIL_USER_CUSTOM_FIELDS` settings, we recommend customizing them via the viewset instead, as explained below. The aforementioned settings might be deprecated in a future release. -``` - (custom_userviewset)= -## Custom `UserViewSet` +## Creating a custom `UserViewSet` -Alternatively, you can also customize the forms and the views by creating a `UserViewSet` subclass. For example, with the above custom form classes, you can create the following `UserViewSet` subclass: +```{versionadded} 6.2 +The ability to customize the `UserViewSet` was added. +``` + +To make use of the custom forms, create a `UserViewSet` subclass. ```python +# myapp/viewsets.py from wagtail.users.views.users import UserViewSet as WagtailUserViewSet from .forms import CustomUserCreationForm, CustomUserEditForm @@ -105,14 +107,15 @@ class UserViewSet(WagtailUserViewSet): return CustomUserCreationForm ``` -Then, configure the `wagtail.users` application to use the custom viewset, by setting up a custom `AppConfig` class. Within your project folder (which will be the package containing the top-level settings and urls modules), create `apps.py` (if it does not exist already) and add: +Then, configure the `wagtail.users` application to use the custom viewset, by setting up a custom `AppConfig` class. Within your custom `myapp` app directory, create `apps.py` (if it does not exist already) and add: ```python +# myapp/apps.py from wagtail.users.apps import WagtailUsersAppConfig class CustomUsersAppConfig(WagtailUsersAppConfig): - user_viewset = "myapplication.someapp.viewsets.UserViewSet" + user_viewset = "myapp.viewsets.UserViewSet" ``` Replace `wagtail.users` in `settings.INSTALLED_APPS` with the path to `CustomUsersAppConfig`. @@ -120,10 +123,29 @@ Replace `wagtail.users` in `settings.INSTALLED_APPS` with the path to `CustomUse ```python INSTALLED_APPS = [ ..., - "myapplication.apps.CustomUsersAppConfig", + "myapp.apps.CustomUsersAppConfig", # "wagtail.users", ..., ] ``` -If you want to customize the group forms and views, see [](customizing_group_views). +The `UserViewSet` class is a subclass of {class}`~wagtail.admin.viewsets.model.ModelViewSet` and thus it supports most of [the customizations available for `ModelViewSet`](generic_views). For example, you can use a custom directory for the templates by setting {attr}`~wagtail.admin.viewsets.model.ModelViewSet.template_prefix`: + +```py +class UserViewSet(WagtailUserViewSet): + template_prefix = "myapp/users/" +``` + +or customize the create and edit templates specifically: + +```py +class UserViewSet(WagtailUserViewSet): + create_template_name = "myapp/users/create.html" + edit_template_name = "myapp/users/edit.html" +``` + +```{versionchanged} 6.2 +Instead of customizing the forms via the [`WAGTAIL_USER_EDIT_FORM`, `WAGTAIL_USER_CREATION_FORM`, and `WAGTAIL_USER_CUSTOM_FIELDS` settings](user_form_settings), we recommend customizing them via the viewset instead, as explained above. The aforementioned settings will be deprecated in a future release. +``` + +The group forms and views can be customized in a similar way – see [](customizing_group_views). diff --git a/docs/extending/customizing_group_views.md b/docs/extending/customizing_group_views.md index dcf9ea8d6e..3b0df6f7dc 100644 --- a/docs/extending/customizing_group_views.md +++ b/docs/extending/customizing_group_views.md @@ -12,6 +12,7 @@ Let's say you need to connect Active Directory groups with Django groups. We create a model for Active Directory groups as follows: ```python +# myapp/models.py from django.contrib.auth.models import Group from django.db import models @@ -32,6 +33,7 @@ However, there is no role field on the Wagtail group 'edit' or 'create' view. To add it, inherit from `wagtail.users.forms.GroupForm` and add a new field: ```python +# myapp/forms.py from django import forms from wagtail.users.forms import GroupForm as WagtailGroupForm @@ -65,6 +67,7 @@ class GroupForm(WagtailGroupForm): Now add your custom form into the group viewset by inheriting the default Wagtail `GroupViewSet` class and overriding the `get_form_class` method. ```python +# myapp/viewsets.py from wagtail.users.views.groups import GroupViewSet as WagtailGroupViewSet from .forms import GroupForm @@ -86,14 +89,15 @@ Add the field to the group 'edit'/'create' templates: {% endblock extra_fields %} ``` -Finally, we configure the `wagtail.users` application to use the custom viewset, by setting up a custom `AppConfig` class. Within your project folder (which will be the package containing the top-level settings and urls modules), create `apps.py` (if it does not exist already) and add: +Finally, we configure the `wagtail.users` application to use the custom viewset, by setting up a custom `AppConfig` class. Within your custom `myapp` app directory, create `apps.py` (if it does not exist already) and add: ```python +# myapp/apps.py from wagtail.users.apps import WagtailUsersAppConfig class CustomUsersAppConfig(WagtailUsersAppConfig): - group_viewset = "myapplication.someapp.viewsets.GroupViewSet" + group_viewset = "myapp.viewsets.GroupViewSet" ``` Replace `wagtail.users` in `settings.INSTALLED_APPS` with the path to `CustomUsersAppConfig`. @@ -101,13 +105,15 @@ Replace `wagtail.users` in `settings.INSTALLED_APPS` with the path to `CustomUse ```python INSTALLED_APPS = [ ..., - "myapplication.apps.CustomUsersAppConfig", + "myapp.apps.CustomUsersAppConfig", # "wagtail.users", ..., ] ``` -If you want to customize the user forms and views instead, see [](custom_userviewset). +The `GroupViewSet` class is a subclass of {class}`~wagtail.admin.viewsets.model.ModelViewSet` and thus it supports most of [the customizations available for `ModelViewSet`](./generic_views). + +The user forms and views can be customized in a similar way - see [](custom_userviewset). (customizing_group_views_permissions_order)= diff --git a/docs/reference/settings.md b/docs/reference/settings.md index c0a7671cd6..3770cb3b54 100644 --- a/docs/reference/settings.md +++ b/docs/reference/settings.md @@ -504,6 +504,8 @@ WAGTAILADMIN_USER_PASSWORD_RESET_FORM = 'users.forms.PasswordResetForm' Allows the default `PasswordResetForm` to be extended with extra fields. +(user_form_settings)= + ### `WAGTAIL_USER_EDIT_FORM` ```python