mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-21 13:31:54 +00:00
Added hooks for user for create, delete, and edit actions
This commit is contained in:
parent
a28fa5e8c8
commit
7859627a6e
5 changed files with 265 additions and 0 deletions
|
|
@ -15,6 +15,7 @@ Changelog
|
|||
* Moved usage count to the sidebar on the edit page (Kees Hink)
|
||||
* Explorer menu now reflects customisations to the page listing made via the `construct_explorer_page_queryset` hook and `ModelAdmin.exclude_from_explorer` property (Tim Heap)
|
||||
* "Choose another image" button changed to "Change image" to avoid ambiguity (Edd Baldry)
|
||||
* Added hooks `before_create_user`, `after_create_user`, `before_delete_user`, `after_delete_user`, `before_edit_user`, `after_edit_user` (Jon Carmack)
|
||||
* Fix: Do not remove stopwords when generating slugs from non-ASCII titles, to avoid issues with incorrect word boundaries (Sævar Öfjörð Magnússon)
|
||||
* Fix: The PostgreSQL search backend now preserves ordering of the `QuerySet` when searching with `order_by_relevance=False` (Bertrand Bordage)
|
||||
* Fix: Using `modeladmin_register` as a decorator no longer replaces the decorated class with `None` (Tim Heap)
|
||||
|
|
|
|||
|
|
@ -513,6 +513,90 @@ Hooks for customising the way users are directed through the process of creating
|
|||
return items.append( UserbarPuppyLinkItem() )
|
||||
|
||||
|
||||
Admin workflow
|
||||
--------------
|
||||
Hooks for customising the way admins are directed through the process of editing users.
|
||||
|
||||
|
||||
.. _after_create_user:
|
||||
|
||||
``after_create_user``
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Do something with a ``User`` object after it has been saved to the database. The callable passed to this hook should take a ``request`` object and a ``user`` object. The function does not have to return anything, but if an object with a ``status_code`` property is returned, Wagtail will use it as a response object. By default, Wagtail will instead redirect to the User index page.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.http import HttpResponse
|
||||
|
||||
from wagtail.wagtailcore import hooks
|
||||
|
||||
@hooks.register('after_create_user')
|
||||
def do_after_page_create(request, user):
|
||||
return HttpResponse("Congrats on creating a new user!", content_type="text/plain")
|
||||
|
||||
|
||||
.. _before_create_user:
|
||||
|
||||
``before_create_user``
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Called at the beginning of the "create user" view passing in the request.
|
||||
|
||||
The function does not have to return anything, but if an object with a ``status_code`` property is returned, Wagtail will use it as a response object and skip the rest of the view.
|
||||
|
||||
Unlike, ``after_create_user``, this is run both for both ``GET`` and ``POST`` requests.
|
||||
|
||||
This can be used to completely override the user editor on a per-view basis:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from wagtail.wagtailcore import hooks
|
||||
|
||||
from .models import AwesomePage
|
||||
from .admin_views import edit_awesome_page
|
||||
|
||||
@hooks.register('before_create_user')
|
||||
def before_create_page(request):
|
||||
return HttpResponse("A user creation form", content_type="text/plain")
|
||||
|
||||
|
||||
|
||||
.. _after_delete_user:
|
||||
|
||||
``after_delete_user``
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Do something after a ``User`` object is deleted. Uses the same behavior as ``after_create_user``.
|
||||
|
||||
|
||||
.. _before_delete_user:
|
||||
|
||||
``before_delete_user``
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Called at the beginning of the "delete user" view passing in the request and the user object.
|
||||
|
||||
Uses the same behavior as ``before_create_user``.
|
||||
|
||||
|
||||
.. _after_edit_user:
|
||||
|
||||
``after_edit_user``
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Do something with a ``User`` object after it has been updated. Uses the same behavior as ``after_create_user``.
|
||||
|
||||
|
||||
.. _before_edit_user:
|
||||
|
||||
``before_edit_user``
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Called at the beginning of the "edit user" view passing in the request and the user object.
|
||||
|
||||
Uses the same behavior as ``before_create_user``.
|
||||
|
||||
Choosers
|
||||
--------
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ Other features
|
|||
* Moved usage count to the sidebar on the edit page (Kees Hink)
|
||||
* Explorer menu now reflects customisations to the page listing made via the `construct_explorer_page_queryset` hook and `ModelAdmin.exclude_from_explorer` property (Tim Heap)
|
||||
* "Choose another image" button changed to "Change image" to avoid ambiguity (Edd Baldry)
|
||||
* Added hooks ``before_create_user``, ``after_create_user``, ``before_delete_user``, ``after_delete_user``, ``before_edit_user``, ``after_edit_user`` (Jon Carmack)
|
||||
|
||||
Bug fixes
|
||||
~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from django.contrib.auth import get_user_model
|
|||
from django.contrib.auth.models import Group, Permission
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
from django.utils import six
|
||||
|
|
@ -328,6 +329,61 @@ class TestUserCreateView(TestCase, WagtailTestUtils):
|
|||
self.assertEqual(users.first().email, 'test@user.com')
|
||||
self.assertFalse(users.first().has_usable_password())
|
||||
|
||||
def test_before_create_user_hook(self):
|
||||
def hook_func(request):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('before_create_user', hook_func):
|
||||
response = self.client.get(
|
||||
reverse('wagtailusers_users:add')
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_before_create_user_hook_post(self):
|
||||
def hook_func(request):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('before_create_user', hook_func):
|
||||
post_data = {
|
||||
'username': "testuser",
|
||||
'email': "testuser@test.com",
|
||||
'password1': 'password12',
|
||||
'password2': 'password12',
|
||||
'first_name': 'test',
|
||||
'last_name': 'user',
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse('wagtailusers_users:add'),
|
||||
post_data
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_after_create_user_hook(self):
|
||||
def hook_func(request, user):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertIsInstance(user, get_user_model())
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('after_create_user', hook_func):
|
||||
post_data = {
|
||||
'username': "testuser",
|
||||
'email': "testuser@test.com",
|
||||
'password1': 'password12',
|
||||
'password2': 'password12',
|
||||
'first_name': 'test',
|
||||
'last_name': 'user',
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse('wagtailusers_users:add'),
|
||||
post_data
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
|
||||
class TestUserDeleteView(TestCase, WagtailTestUtils):
|
||||
def setUp(self):
|
||||
|
|
@ -387,6 +443,45 @@ class TestUserDeleteView(TestCase, WagtailTestUtils):
|
|||
users = get_user_model().objects.filter(username='testsuperuser')
|
||||
self.assertEqual(users.count(), 0)
|
||||
|
||||
def test_before_delete_user_hook(self):
|
||||
def hook_func(request, user):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(user.pk, self.test_user.pk)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('before_delete_user', hook_func):
|
||||
response = self.client.get(reverse('wagtailusers_users:delete', args=(self.test_user.pk, )))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_before_delete_user_hook_post(self):
|
||||
def hook_func(request, user):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(user.pk, self.test_user.pk)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('before_delete_user', hook_func):
|
||||
response = self.client.post(reverse('wagtailusers_users:delete', args=(self.test_user.pk, )))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_after_delete_user_hook(self):
|
||||
def hook_func(request, user):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(user.username, self.test_user.username)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('after_delete_user', hook_func):
|
||||
response = self.client.post(reverse('wagtailusers_users:delete', args=(self.test_user.pk, )))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
|
||||
class TestUserDeleteViewForNonSuperuser(TestCase, WagtailTestUtils):
|
||||
def setUp(self):
|
||||
|
|
@ -703,6 +798,65 @@ class TestUserEditView(TestCase, WagtailTestUtils):
|
|||
self.assertEqual(user.first_name, 'Edited')
|
||||
self.assertTrue(user.check_password('password'))
|
||||
|
||||
def test_before_edit_user_hook(self):
|
||||
def hook_func(request, user):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(user.pk, self.test_user.pk)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('before_edit_user', hook_func):
|
||||
response = self.client.get(reverse('wagtailusers_users:edit', args=(self.test_user.pk, )))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_before_edit_user_hook_post(self):
|
||||
def hook_func(request, user):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(user.pk, self.test_user.pk)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('before_edit_user', hook_func):
|
||||
post_data = {
|
||||
'username': "testuser",
|
||||
'email': "test@user.com",
|
||||
'first_name': "Edited",
|
||||
'last_name': "User",
|
||||
'password1': "password",
|
||||
'password2': "password",
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse('wagtailusers_users:edit', args=(self.test_user.pk, )), post_data
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
def test_after_edit_user_hook_post(self):
|
||||
def hook_func(request, user):
|
||||
self.assertIsInstance(request, HttpRequest)
|
||||
self.assertEqual(user.pk, self.test_user.pk)
|
||||
|
||||
return HttpResponse("Overridden!")
|
||||
|
||||
with self.register_hook('after_edit_user', hook_func):
|
||||
post_data = {
|
||||
'username': "testuser",
|
||||
'email': "test@user.com",
|
||||
'first_name': "Edited",
|
||||
'last_name': "User",
|
||||
'password1': "password",
|
||||
'password2': "password",
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse('wagtailusers_users:edit', args=(self.test_user.pk, )), post_data
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.content, b"Overridden!")
|
||||
|
||||
|
||||
class TestUserProfileCreation(TestCase, WagtailTestUtils):
|
||||
def setUp(self):
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ from wagtail.wagtailadmin import messages
|
|||
from wagtail.wagtailadmin.forms import SearchForm
|
||||
from wagtail.wagtailadmin.utils import (
|
||||
any_permission_required, permission_denied, permission_required)
|
||||
from wagtail.wagtailcore import hooks
|
||||
from wagtail.wagtailcore.compat import AUTH_USER_APP_LABEL, AUTH_USER_MODEL_NAME
|
||||
from wagtail.wagtailusers.forms import UserCreationForm, UserEditForm
|
||||
from wagtail.wagtailusers.utils import user_can_delete_user
|
||||
|
|
@ -122,6 +123,10 @@ def index(request):
|
|||
|
||||
@permission_required(add_user_perm)
|
||||
def create(request):
|
||||
for fn in hooks.get_hooks('before_create_user'):
|
||||
result = fn(request)
|
||||
if hasattr(result, 'status_code'):
|
||||
return result
|
||||
if request.method == 'POST':
|
||||
form = get_user_creation_form()(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
|
|
@ -129,6 +134,10 @@ def create(request):
|
|||
messages.success(request, _("User '{0}' created.").format(user), buttons=[
|
||||
messages.button(reverse('wagtailusers_users:edit', args=(user.pk,)), _('Edit'))
|
||||
])
|
||||
for fn in hooks.get_hooks('after_create_user'):
|
||||
result = fn(request, user)
|
||||
if hasattr(result, 'status_code'):
|
||||
return result
|
||||
return redirect('wagtailusers_users:index')
|
||||
else:
|
||||
messages.error(request, _("The user could not be created due to errors."))
|
||||
|
|
@ -146,6 +155,10 @@ def edit(request, user_id):
|
|||
can_delete = user_can_delete_user(request.user, user)
|
||||
editing_self = request.user == user
|
||||
|
||||
for fn in hooks.get_hooks('before_edit_user'):
|
||||
result = fn(request, user)
|
||||
if hasattr(result, 'status_code'):
|
||||
return result
|
||||
if request.method == 'POST':
|
||||
form = get_user_edit_form()(request.POST, request.FILES, instance=user, editing_self=editing_self)
|
||||
if form.is_valid():
|
||||
|
|
@ -153,6 +166,10 @@ def edit(request, user_id):
|
|||
messages.success(request, _("User '{0}' updated.").format(user), buttons=[
|
||||
messages.button(reverse('wagtailusers_users:edit', args=(user.pk,)), _('Edit'))
|
||||
])
|
||||
for fn in hooks.get_hooks('after_edit_user'):
|
||||
result = fn(request, user)
|
||||
if hasattr(result, 'status_code'):
|
||||
return result
|
||||
return redirect('wagtailusers_users:index')
|
||||
else:
|
||||
messages.error(request, _("The user could not be saved due to errors."))
|
||||
|
|
@ -173,9 +190,17 @@ def delete(request, user_id):
|
|||
if not user_can_delete_user(request.user, user):
|
||||
return permission_denied(request)
|
||||
|
||||
for fn in hooks.get_hooks('before_delete_user'):
|
||||
result = fn(request, user)
|
||||
if hasattr(result, 'status_code'):
|
||||
return result
|
||||
if request.method == 'POST':
|
||||
user.delete()
|
||||
messages.success(request, _("User '{0}' deleted.").format(user))
|
||||
for fn in hooks.get_hooks('after_delete_user'):
|
||||
result = fn(request, user)
|
||||
if hasattr(result, 'status_code'):
|
||||
return result
|
||||
return redirect('wagtailusers_users:index')
|
||||
|
||||
return render(request, "wagtailusers/users/confirm_delete.html", {
|
||||
|
|
|
|||
Loading…
Reference in a new issue