Allow hook override of user profile avatar url in admin tags (#12689)

Fixes #12661
pull/12486/merge
jhrr 2024-12-04 14:59:19 +00:00 zatwierdzone przez Matt Westcott
rodzic 9889bddcb8
commit 5402010d16
8 zmienionych plików z 82 dodań i 0 usunięć

Wyświetl plik

@ -15,6 +15,7 @@ Changelog
* Only allow selection of valid new parents within the copy Page view (Mauro Soche)
* Add `on_serve_page` hook to modify the serving chain of pages (Krystian Magdziarz, Dawid Bugajewski)
* Add support for `WAGTAIL_GRAVATAR_PROVIDER_URL` URLs with query string parameters (Ayaan Qadri, Guilhem Saurel)
* Add `get_avatar_url` hook to customise user avatars (jhrr)
* Fix: Improve handling of translations for bulk page action confirmation messages (Matt Westcott)
* Fix: Ensure custom rich text feature icons are correctly handled when provided as a list of SVG paths (Temidayo Azeez, Joel William, LB (Ben) Johnston)
* Fix: Ensure manual edits to `StreamField` values do not throw an error (Stefan Hammer)

Wyświetl plik

@ -862,6 +862,7 @@
* Mauro Soche
* Krystian Magdziarz
* Guilhem Saurel
* jhrr
## Translators

Wyświetl plik

@ -85,6 +85,22 @@ To replace the welcome message on the dashboard, create a template file `dashboa
{% block branding_welcome %}Welcome to Frank's Site{% endblock %}
```
(custom_user_profile_avatar)=
## Custom user profile avatar
To render a user avatar other than the one sourced from the `UserProfile` model or from [gravatar](https://gravatar.com/), you can use the [`get_avatar_url`](#get_avatar_url) hook and resolve the avatar's image url as you see fit.
For example, you might have an avatar on a `Profile` model in your own application that is keyed to the `auth.User` model in the familiar pattern. In that case, you could register your hook as the in following example, and the Wagtail admin avatar will be replaced with your own `Profile` avatar accordingly.
```python
@hooks.register('get_avatar_url')
def get_profile_avatar(user, size):
return user.profile.avatar
```
Additionally, you can use the default `size` parameter that is passed in to the hook if you need to attach it to a request or do any further processing on your image.
(custom_user_interface_fonts)=
## Custom user interface fonts

Wyświetl plik

@ -102,6 +102,30 @@ depth: 1
---
```
## Appearance
Hooks for modifying the display and appearance of basic CMS features and furniture.
(get_avatar_url)=
### `get_avatar_url`
Specify a custom user avatar to be displayed in the Wagtail admin. The callable passed to this hook should accept a `user` object and a `size` parameter that can be used in any resize or thumbnail processing you might need to do.
```python
from datetime import datetime
@hooks.register('get_avatar_url')
def get_profile_avatar(user, size):
today = datetime.now()
is_christmas_day = today.month == 12 and today.day == 25
if is_christmas_day:
return '/static/images/santa.png'
return None
```
## Admin modules
Hooks for building new areas of the admin interface (alongside pages, images, documents, and so on).

Wyświetl plik

@ -24,6 +24,7 @@ depth: 1
* Only allow selection of valid new parents within the copy Page view (Mauro Soche)
* Add [`on_serve_page`](on_serve_page) hook to modify the serving chain of pages (Krystian Magdziarz, Dawid Bugajewski)
* Add support for [`WAGTAIL_GRAVATAR_PROVIDER_URL`](wagtail_gravatar_provider_url) URLs with query string parameters (Ayaan Qadri, Guilhem Saurel)
* Add [`get_avatar_url`](get_avatar_url) hook to customise user avatars (jhrr)
### Bug fixes

Wyświetl plik

@ -654,8 +654,19 @@ def avatar_url(user, size=50, gravatar_only=False):
"""
A template tag that receives a user and size and return
the appropriate avatar url for that user.
If the 'get_avatar_url' hook is defined, then that will intercept this
logic and point to whatever resource that function returns. In this way,
users can swap out the Wagtail UserProfile avatar for some other image or
field of their own choosing without needing to alter anything on the
existing models.
Example usage: {% avatar_url request.user 50 %}
"""
for hook_fn in hooks.get_hooks("get_avatar_url"):
if url := hook_fn(user, size):
return url
if (
not gravatar_only

Wyświetl plik

@ -1,4 +1,5 @@
import json
import os
import unittest
from datetime import datetime, timedelta
from datetime import timezone as dt_timezone
@ -31,6 +32,24 @@ from wagtail.users.models import UserProfile
from wagtail.utils.deprecation import RemovedInWagtail70Warning
class TestAvatarUrlInterceptTemplateTag(WagtailTestUtils, TestCase):
def setUp(self):
self.test_user = self.create_user(
username="testuser",
email="testuser@email.com",
password="password",
)
def test_get_avatar_url_undefined(self):
url = avatar_url(self.test_user)
self.assertIn("www.gravatar.com", url)
@mock.patch.dict(os.environ, {"AVATAR_INTERCEPT": "True"}, clear=True)
def test_get_avatar_url_registered(self):
url = avatar_url(self.test_user)
self.assertEqual(url, "/some/avatar/fred.png")
class TestAvatarTemplateTag(WagtailTestUtils, TestCase):
def setUp(self):
# Create a user

Wyświetl plik

@ -1,3 +1,5 @@
import os
from django import forms
from django.http import HttpResponse
from django.utils.safestring import mark_safe
@ -432,3 +434,10 @@ def register_animated_advert_chooser_viewset():
@hooks.register("register_admin_viewset")
def register_event_page_listing_viewset():
return event_page_listing_viewset
@hooks.register("get_avatar_url")
def register_avatar_intercept_url(user, size):
if os.environ.get("AVATAR_INTERCEPT"):
return "/some/avatar/fred.png"
return None