{"id":2926,"library":"django-axes","title":"django-axes","description":"django-axes is a Django plugin that actively monitors and tracks suspicious login attempts, helping to protect Django-powered sites from brute-force attacks. It can lock out users or IP addresses after a configurable number of failed attempts, supporting various tracking methods like IP, username, and user agent combinations. The library is currently at version 8.3.1 and is actively maintained by the Jazzband community, with a regular release cadence.","status":"active","version":"8.3.1","language":"en","source_language":"en","source_url":"https://github.com/jazzband/django-axes","tags":["django","security","authentication","login","brute-force","rate-limiting"],"install":[{"cmd":"pip install django-axes","lang":"bash","label":"Install stable release"}],"dependencies":[{"reason":"Core framework dependency. django-axes 8.x supports Django 4.2, 5.2, and 6.0, and requires Python >= 3.10. Ensure your Django version is supported by the specific django-axes release you are using.","package":"Django","optional":false},{"reason":"Used by default for client IP address detection. While not a hard dependency, it provides robust IP resolution capabilities. If not installed, you might need to configure custom IP resolution.","package":"django-ipware","optional":true}],"imports":[{"note":"While `AxesBackend` is available for backward compatibility, `AxesStandaloneBackend` is recommended as it doesn't provide permissions-checking functionality, allowing for custom logic if needed. It must be at the top of your `AUTHENTICATION_BACKENDS` list.","wrong":"from axes.backends import AxesBackend","symbol":"AxesStandaloneBackend","correct":"from axes.backends import AxesStandaloneBackend"},{"note":"This middleware handles lockout responses. It should typically be the last middleware in your `MIDDLEWARE` list.","symbol":"AxesMiddleware","correct":"from axes.middleware import AxesMiddleware"},{"note":"Used for custom actions when a user is locked out, e.g., integration with Django REST Framework for custom API responses.","symbol":"axes.signals.user_locked_out","correct":"from django.dispatch import receiver\nfrom axes.signals import user_locked_out"},{"note":"Decorator to prevent a view from triggering axes lockout logic.","symbol":"axes.decorators.axes_prevent_lockout","correct":"from axes.decorators import axes_prevent_lockout"}],"quickstart":{"code":"# settings.py\n\nINSTALLED_APPS = [\n    # ... other Django apps\n    'axes',\n]\n\nAUTHENTICATION_BACKENDS = [\n    'axes.backends.AxesStandaloneBackend',  # Must be first\n    'django.contrib.auth.backends.ModelBackend',\n]\n\nMIDDLEWARE = [\n    # ... other Django middleware\n    'axes.middleware.AxesMiddleware',  # Should be last if overriding auth response\n]\n\n# Optional: Basic configuration\nAXES_FAILURE_LIMIT = 5\nAXES_COOLOFF_TIME = 60 # In minutes or timedelta object (e.g., timedelta(minutes=30))\n# AXES_LOCK_OUT_BY_IP_OR_USERNAME = True # Lock out by IP or username, not both\n\n# Then, run migrations:\n# python manage.py migrate\n# And check your configuration:\n# python manage.py check","lang":"python","description":"To quickly set up django-axes, add 'axes' to `INSTALLED_APPS`, configure `AUTHENTICATION_BACKENDS` to include `AxesStandaloneBackend` at the top, and add `AxesMiddleware` to your `MIDDLEWARE` list, preferably at the end. Finally, run `migrate` to create necessary database tables and `check` to verify your configuration. You can then adjust settings like `AXES_FAILURE_LIMIT` and `AXES_COOLOFF_TIME`."},"warnings":[{"fix":"Review `axes.handlers.database.AxesDatabaseHandler` for new API calls and refactor any custom logic. Refer to the upgrade notes for specific changes.","message":"Version 8.0.0 moved all database-related logic into `axes.handlers.database.AxesDatabaseHandler`. If you had custom handlers or directly accessed internal database functions related to attempts, you will need to refactor your code to use the new handler methods.","severity":"breaking","affected_versions":"8.0.0+"},{"fix":"Consult the version 7 upgrade notes in the official documentation. This will likely involve changes if you customized lockout responses or relied on the deprecated `AxesHttpRequest` object.","message":"Version 7.0.0 introduced significant breaking changes related to dynamic cooloff time calculation and lockout response handling. The lockout response calculation changed to request flagging instead of throwing exceptions, and `axes.request.AxesHttpRequest` object type definition was deprecated.","severity":"breaking","affected_versions":"7.0.0+"},{"fix":"Explicitly define `AXES_USERNAME_FORM_FIELD = 'your_username_field_name'` in `settings.py` to match your user model's `USERNAME_FIELD` or your login form's username field.","message":"As of version 7.0.2, `AXES_USERNAME_FORM_FIELD` now defaults to `settings.AUTH_USER_MODEL.USERNAME_FIELD`. Previously, it hardcoded to 'username'. If you use a custom user model with a different username field or a custom login form with a non-standard username field name (e.g., 'email'), you must explicitly set `AXES_USERNAME_FORM_FIELD` in your `settings.py` to prevent `AccessAttempt` records from having a `None` username.","severity":"gotcha","affected_versions":"7.0.2+"},{"fix":"Ensure `AUTHENTICATION_BACKENDS = ['axes.backends.AxesStandaloneBackend', 'django.contrib.auth.backends.ModelBackend', ...]`.","message":"Incorrect order of `AUTHENTICATION_BACKENDS` can lead to axes not functioning correctly. `AxesStandaloneBackend` (or `AxesBackend`) *must* be the first item in your `AUTHENTICATION_BACKENDS` list in `settings.py`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Configure a persistent and shared cache backend like Memcached or Redis (`django.core.cache.backends.memcached.MemcachedCache`, `django.core.cache.backends.redis.RedisCache`) for accurate tracking across multiple processes.","message":"If using a multi-process server (e.g., Gunicorn with multiple workers) or a distributed environment, using `django.core.cache.backends.locmem.LocMemCache` or `FileBasedCache` as your cache backend can lead to inconsistent behavior for Axes, as attempts might not be shared across processes.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Upgrade to `django-axes` 5.32 or newer and set `AXES_RESET_COOL_OFF_ON_FAILURE_DURING_LOCKOUT = False` in your `settings.py` to prevent the cool-off period from resetting.","message":"Prior to version 5.32, a common behavior was that the cool-off timer would reset on any subsequent failed login attempts during an existing lockout period. This could inadvertently extend the lockout time indefinitely.","severity":"gotcha","affected_versions":"< 5.32"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}