NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1877 most downloaded on PyPI
A pluggable framework for adding two-factor authentication to Django using one-time passwords.
Last release 28 days ago
06 Sep 2026
Release timing varies
gaps range from 2 weeks to 8 months
Nearly every release is documented
notes for 57 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
14 years old
88 releases · first in 2012
Bump version: 1.7.2 → 1.7.3
Bump version: 1.7.2 → 1.7.3
Bump version: 1.7.1 → 1.7.2
Bump version: 1.7.1 → 1.7.2
#190: OverflowError on the admin login page when a device's throttling failure count is high (Varun Juneja)
One column per quarter.
Bump version: 1.7.0 → 1.7.1
Bump version: 1.7.0 → 1.7.1
Routine test matrix update
#188: Fix authentication form inappropriately triggering rate-limiting
Thanks to Varun Juneja.
Bump version: 1.6.3 → 1.7.0
Bump version: 1.6.3 → 1.7.0
Bump version: 1.6.2 → 1.6.3
Bump version: 1.6.1 → 1.6.2
Bump version: 1.6.1 → 1.6.2
Bump version: 1.6.0 → 1.6.1
Bump version: 1.6.0 → 1.6.1
Bump version: 1.5.4 → 1.6.0
Bump version: 1.5.4 → 1.6.0
Bump version: 1.5.3 → 1.5.4
Bump version: 1.5.3 → 1.5.4
Bump version: 1.5.2 → 1.5.3
Bump version: 1.5.2 → 1.5.3
Bump version: 1.5.1 → 1.5.2
Bump version: 1.5.1 → 1.5.2
Bump version: 1.5.0 → 1.5.1
Bump version: 1.5.0 → 1.5.1
Previously, only the qrcode_ library was supported.
See the ~django_otp.plugins.otp_email.models.EmailDevice documentation for API details.
#140: Support customization of email delivery.
See the ~django_otp.plugins.otp_email.models.EmailDevice documentation for API details.
Support translation of the "sent by email" message.
Add a new TimestampMixin with created_at and last_used_at fields for device models.
#137: Add TimestampMixin
Add a new TimestampMixin with created_at and last_used_at fields for device models.
All builtin plugins now have these timestamp fields and require migrating.
Some documentation cleanup.
Devices that generate random tokens can take advantage of the new ~django_otp.models.CooldownMixin to enforce limits on how frequently new tokens can
#122: Added throttling to token generation.
Devices that generate random tokens can take advantage of the new ~django_otp.models.CooldownMixin to enforce limits on how frequently new tokens can be generated (and presumably delivered). ~django_otp.plugins.otp_email.models.EmailDevice uses this and has a default cooldown configured.
Thanks to Demetris Stavrou for this feature.
Note: ~django_otp.models.VerifyNotAllowed is now an ~enum.Enum. This will break any code that inadvisably hard-coded the string value of the N_FAILED_ATTEMPTS property.
.. _#133: https://github.com/django-otp/django-otp/pull/133
#133: Add pt-PT translation.
.. _#131: https://github.com/django-otp/django-otp/pull/131
#131: Fix German translation
.. _#125: https://github.com/django-otp/django-otp/pull/125
#125: Support email body_html templates
.. _#124: https://github.com/django-otp/django-otp/pull/124
#124: Add pt-BR translations.
This project is now managed with hatch_, which replaces setuptools, pipenv, and tox. Users of the package should not be impacted. Developers can refer
This project is now managed with hatch, which replaces setuptools, pipenv, and tox. Users of the package should not be impacted. Developers can refer to the readme for details. If you're packaging this project from source, I suggest relying on pip's isolated builds rather than using hatch directly.
#123: Add support for passing an image parameter in the otpauth URL. See OTP_TOTP_IMAGE.
.. _#116: https://github.com/django-otp/django-otp/pull/116
#116: Add German translation
.. _#115: https://github.com/django-otp/django-otp/pull/115
#115: Force OTP_EMAIL_SUBJECT to be a string
.. _#106: https://github.com/django-otp/django-otp/pull/106
#106: Add Spanish translation
.. _#89: https://github.com/django-otp/django-otp/pull/89
#89: Use the standard username context variable for compatibility.
.. _#93: https://github.com/django-otp/django-otp/issues/93
#93: Default to AutoField to avoid spurious migrations.
.. _#87: https://github.com/django-otp/django-otp/issues/87
#87: Fix locked_until key in throttling reason map.
Where possible, all APIs now verify tokens atomically. This prevents race conditions that could result in a token being verified twice as well as clos
Where possible, all APIs now verify tokens atomically. This prevents race conditions that could result in a token being verified twice as well as closing gaps in throttling enforcement. Low-level integrators may still need to manage their own transactions.
.. _#82: https://github.com/django-otp/django-otp/issues/82
#82: Add ability to pass extra context when rendering ~django_otp.plugins.otp_email.models.EmailDevice templates.
.. _#77: https://github.com/django-otp/django-otp/issues/77
#77: Force username to a string in config_url. Note that this might not produce a very human-friendly result, but it shouldn't throw an exception.
.. _#76: https://github.com/django-otp/django-otp/issues/76
#76: Django 3.2 supports the prefers-color-scheme media query, so we need to force a white background for QR codes.
.. _#71: https://github.com/django-otp/django-otp/issues/71
#71: Provide time at which throttling lock expires.
Added a setting to load the email body template from a template file.
Added a setting to load the email body template from a template file.
Added contributed French string translations.
Added contributed French string translations.
Dropped support for Django < 2.2.
Dropped support for Django < 2.2.
.. _#49: https://github.com/django-otp/django-otp/issues/49
#49: Hide the navigation sidebar on the login page.
Stricter authorization checks for qrcodes in the admin interface.
Stricter authorization checks for qrcodes in the admin interface.
Nothing published for this version
.. _#38: https://github.com/django-otp/django-otp/pull/38
#38: Update admin fields for ~django_otp.plugins.otp_email.models.EmailDevice.
~django_otp.models.SideChannelDevice is a new abstract device class to simplify writing devices that deliver tokens to the user by other channels (ema
~django_otp.models.SideChannelDevice is a new abstract device class to simplify writing devices that deliver tokens to the user by other channels (email, SMS, etc.).
#33, #34 (arjan-s): Implement ~django_otp.models.SideChannelDevice, reimplement ~django_otp.plugins.otp_email.models.EmailDevice on top of it, and add a few settings for customization.
Add rate limiting to ~django_otp.plugins.otp_email.models.EmailDevice and ~django_otp.plugins.otp_static.models.StaticDevice.
.. _#26: https://github.com/django-otp/django-otp/issues/26
#26: Display OTP Token field on the login page even when user has not yet authenticated.
.. _#17: https://github.com/django-otp/django-otp/pull/17 .. _#18: https://github.com/django-otp/django-otp/pull/18 .. _#23: https://github.com/django
.. _#15: https://github.com/django-otp/django-otp/issues/15
#15: Add admin template for Django 3.0.
.. _#10: https://github.com/django-otp/django-otp/issues/10
#10: Remove old admin login templates that are confusing some unrelated tools.
Built-in forms have autocomplete disabled for token widgets.
Built-in forms have autocomplete disabled for token widgets.
Fixed miscellaneous typos.
.. _#2: https://github.com/django-otp/django-otp/issues/2
#2: Fix LoginView for already-authenticated users, with multiple auth backends configured.
Removed dependencies on Python 2 compatibility shims in Django < 3.0.
Removed dependencies on Python 2 compatibility shims in Django < 3.0.
Removed obsolete compatibility shims. The testing and support matrix is unchanged from 0.6.0, so there should be no impact.
Removed obsolete compatibility shims. The testing and support matrix is unchanged from 0.6.0, so there should be no impact.
Built-in HOTP and TOTP devices are now rate-limited, enforcing exponentially increasing delays between successive failures. See the device documentati
Built-in HOTP and TOTP devices are now rate-limited, enforcing exponentially increasing delays between successive failures. See the device documentation for information on presenting more useful error messages when this happens, as well as for tuning (or disabling) this behavior.
Thanks to Luke Plant for the idea and implementation.
Fix encoding of otpauth:// URL parameters.
Fix encoding of otpauth:// URL parameters.
Error messages in ~django_otp.forms.OTPAuthenticationForm and ~django_otp.forms.OTPTokenForm can be customized.
Error messages in ~django_otp.forms.OTPAuthenticationForm and ~django_otp.forms.OTPTokenForm can be customized.
Remove dependencies on old non-class login views.
Remove dependencies on old non-class login views.
Drop support for Django < 1.11.
Fix return type of ~django_otp.plugins.otp_static.models.StaticToken.random_token.
Fix return type of ~django_otp.plugins.otp_static.models.StaticToken.random_token.
Fix addstatictoken string handling under Python 3.
Fix addstatictoken string handling under Python 3.
Nothing published for this version
Improved handling of device persistent identifiers.
Improved handling of device persistent identifiers.
Make sure default keys are unicode values.
Nothing published for this version
Update addstatictoken command for current Django versions.
Update addstatictoken command for current Django versions.
Allow verified users to be pickled.
Allow verified users to be pickled.
Minor fixes for Django 1.11 and 2.0.
Minor fixes for Django 1.11 and 2.0.
Your coding agent can read these notes before it upgrades. Set up the MCP server →