diff --git a/jazzmin/templatetags/jazzmin.py b/jazzmin/templatetags/jazzmin.py index aa4ff145..7f24dfc2 100644 --- a/jazzmin/templatetags/jazzmin.py +++ b/jazzmin/templatetags/jazzmin.py @@ -190,7 +190,9 @@ def get_user_avatar(user: AbstractUser) -> str: # If we find the property directly on the user model (imagefield or URLfield) avatar_field = getattr(user, avatar_field_name, None) - if avatar_field: + if avatar_field is not None: + if not avatar_field: + return no_avatar if isinstance(avatar_field, str): return avatar_field elif hasattr(avatar_field, "url"): @@ -198,7 +200,7 @@ def get_user_avatar(user: AbstractUser) -> str: elif callable(avatar_field): return avatar_field() - logger.warning("avatar field must be an ImageField/URLField on the user model, or a callable") + logger.warning("Avatar field must be an ImageField/URLField on the user model, or a callable") return no_avatar diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py index 03da7a7b..bb79fadd 100644 --- a/tests/test_templatetags.py +++ b/tests/test_templatetags.py @@ -1,5 +1,5 @@ import json -from unittest.mock import MagicMock +from unittest.mock import MagicMock, NonCallableMock import pytest from django.contrib.admin.models import CHANGE, LogEntry @@ -50,16 +50,46 @@ def test_style_bold_first_word(): @pytest.mark.django_db @pytest.mark.parametrize( - "case,test_input,field,expected", + "case,test_input,field,expected,log", [ - (1, MagicMock(avatar="image.jpg"), "avatar", "image.jpg"), - (2, MagicMock(avatar="image.jpg"), lambda u: u.avatar, "image.jpg"), - (3, MagicMock(avatar=MagicMock(url="image.jpg")), "avatar", "image.jpg"), + (1, MagicMock(avatar="image.jpg"), "avatar", "image.jpg", None), + (2, MagicMock(avatar="image.jpg"), lambda u: u.avatar, "image.jpg", None), + (3, MagicMock(avatar=MagicMock(url="image.jpg")), "avatar", "image.jpg", None), + # Properly set file field but empty (no image uploaded) + ( + 4, + MagicMock(avatar=MagicMock(__bool__=lambda x: False)), + "avatar", + "/static/vendor/adminlte/img/user2-160x160.jpg", + None, + ), + # No avatar field set + ( + 5, + MagicMock( + avatar="image.jpg", + ), + None, + "/static/vendor/adminlte/img/user2-160x160.jpg", + None, + ), + # No proper avatar field set + ( + 6, + MagicMock(avatar=NonCallableMock(spec_set=["__bool__"], __bool__=lambda x: True)), + "avatar", + "/static/vendor/adminlte/img/user2-160x160.jpg", + "Avatar field must be", + ), ], ) -def test_get_user_avatar(case, test_input, field, expected, custom_jazzmin_settings): +def test_get_user_avatar(case, test_input, field, expected, log, custom_jazzmin_settings, caplog): """ We can specify the name of a charfield or imagefield on our user model, or a callable that receives our user """ custom_jazzmin_settings["user_avatar"] = field assert jazzmin.get_user_avatar(test_input) == expected + if log: + assert log in caplog.text + else: + assert not caplog.text