mirror of
https://github.com/jazzband/django-axes.git
synced 2026-03-16 22:30:23 +00:00
Fix circular import with custom user models
Fixes #1280 - Use SimpleLazyObject to defer get_user_model() evaluation - Prevents circular import when custom user models import from axes - Add test coverage for lazy evaluation in test_conf.py
This commit is contained in:
parent
95a8043341
commit
6703b66f17
2 changed files with 53 additions and 1 deletions
|
|
@ -1,5 +1,6 @@
|
|||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
# disable plugin when set to False
|
||||
|
|
@ -43,8 +44,14 @@ settings.AXES_ONLY_ADMIN_SITE = getattr(settings, "AXES_ONLY_ADMIN_SITE", False)
|
|||
settings.AXES_ENABLE_ADMIN = getattr(settings, "AXES_ENABLE_ADMIN", True)
|
||||
|
||||
# use a specific username field to retrieve from login POST data
|
||||
def _get_username_field_default():
|
||||
return get_user_model().USERNAME_FIELD
|
||||
|
||||
|
||||
settings.AXES_USERNAME_FORM_FIELD = getattr(
|
||||
settings, "AXES_USERNAME_FORM_FIELD", get_user_model().USERNAME_FIELD
|
||||
settings,
|
||||
"AXES_USERNAME_FORM_FIELD",
|
||||
SimpleLazyObject(_get_username_field_default),
|
||||
)
|
||||
|
||||
# use a specific password field to retrieve from login POST data
|
||||
|
|
|
|||
45
tests/test_conf.py
Normal file
45
tests/test_conf.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
from django.test import TestCase
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
|
||||
|
||||
class ConfTestCase(TestCase):
|
||||
def test_axes_username_form_field_uses_lazy_evaluation(self):
|
||||
"""
|
||||
Test that AXES_USERNAME_FORM_FIELD uses SimpleLazyObject for lazy evaluation.
|
||||
This prevents circular import issues with custom user models (issue #1280).
|
||||
"""
|
||||
from axes.conf import settings
|
||||
|
||||
# Verify that AXES_USERNAME_FORM_FIELD is a SimpleLazyObject if not overridden
|
||||
# This is only the case when the setting is not explicitly defined
|
||||
username_field = settings.AXES_USERNAME_FORM_FIELD
|
||||
|
||||
# The actual type depends on whether AXES_USERNAME_FORM_FIELD was overridden
|
||||
# If it's using the default, it should be a SimpleLazyObject
|
||||
# If overridden in settings, it could be a plain string
|
||||
# Either way, it should be usable as a string
|
||||
|
||||
# Force evaluation and verify it works
|
||||
username_field_str = str(username_field)
|
||||
|
||||
# Should get the default USERNAME_FIELD from the user model
|
||||
# For the test suite, this is "username"
|
||||
self.assertIsInstance(username_field_str, str)
|
||||
self.assertTrue(len(username_field_str) > 0)
|
||||
|
||||
def test_axes_username_form_field_evaluates_correctly(self):
|
||||
"""
|
||||
Test that when AXES_USERNAME_FORM_FIELD is accessed, it correctly
|
||||
resolves to the user model's USERNAME_FIELD.
|
||||
"""
|
||||
from django.contrib.auth import get_user_model
|
||||
from axes.conf import settings
|
||||
|
||||
# Get the expected value
|
||||
expected_username_field = get_user_model().USERNAME_FIELD
|
||||
|
||||
# Get the actual value from axes settings
|
||||
actual_username_field = str(settings.AXES_USERNAME_FORM_FIELD)
|
||||
|
||||
# They should match
|
||||
self.assertEqual(actual_username_field, expected_username_field)
|
||||
Loading…
Reference in a new issue