Describe the bug
Starting with django-axes 8.1.0, the AccessAttemptExpiration model was introduced. If an application does not apply the migration for this model (because the feature is not used), deleting AccessAttempt objects during a successful login triggers deletion logic that attempts to delete a related AccessAttemptExpiration. Since the corresponding table does not exist, this results in an error.
To Reproduce
Steps to reproduce the behavior:
- Install django-axes ≥ 8.1.0.
- Do not apply the
AccessAttemptExpiration migration.
- Make a failed login attempt (creates an
AccessAttempt).
- Perform a successful login.
reset_user_attempts() deletes AccessAttempt and attempts to cascade-delete AccessAttemptExpiration, which does not exist.
Expected behavior
When AccessAttemptExpiration is not used and its migration is not applied, deleting AccessAttempt records should not attempt to access or delete AccessAttemptExpiration, and successful logins should reset attempts without errors.
Your environment
python version: 3.13
django version: 6.0.1
django-axes version: 8.1.0
Operating system: Windows
Additional context
AccessAttemptExpiration is defined as a OneToOneField with on_delete=models.CASCADE. The current reset logic does not guard against the absence of related expiration objects, causing a regression for applications that do not use the new feature.
Describe the bug
Starting with django-axes 8.1.0, the
AccessAttemptExpirationmodel was introduced. If an application does not apply the migration for this model (because the feature is not used), deletingAccessAttemptobjects during a successful login triggers deletion logic that attempts to delete a relatedAccessAttemptExpiration. Since the corresponding table does not exist, this results in an error.To Reproduce
Steps to reproduce the behavior:
AccessAttemptExpirationmigration.AccessAttempt).reset_user_attempts()deletesAccessAttemptand attempts to cascade-deleteAccessAttemptExpiration, which does not exist.Expected behavior
When
AccessAttemptExpirationis not used and its migration is not applied, deletingAccessAttemptrecords should not attempt to access or deleteAccessAttemptExpiration, and successful logins should reset attempts without errors.Your environment
python version: 3.13
django version: 6.0.1
django-axes version: 8.1.0
Operating system: Windows
Additional context
AccessAttemptExpirationis defined as aOneToOneFieldwithon_delete=models.CASCADE. The current reset logic does not guard against the absence of related expiration objects, causing a regression for applications that do not use the new feature.