Skip to content

Instantly share code, notes, and snippets.

@devxpy
Last active January 20, 2018 21:09
Show Gist options
  • Save devxpy/c3fbc1f0689ded064ac0631071f7be92 to your computer and use it in GitHub Desktop.
Save devxpy/c3fbc1f0689ded064ac0631071f7be92 to your computer and use it in GitHub Desktop.
Django dynamic Authentication Form that works with Custom Backends. Can also be used as a drop-in replacement for django-admin login
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import forms as auth_forms, authenticate, get_user_model
from django.utils.text import capfirst
UserModel = get_user_model()
class DynamicAuthenticationForm(auth_forms.AuthenticationForm):
"""
Base class for authenticating users
Extend this to get a form that accept logins on username_field parameter and password.
"""
error_messages = {
'invalid_login': _(
"Please enter a valid %(username_field)s."
),
'wrong_password': _(
"Please enter the correct password. (passwords are case-sensitive)"
),
'inactive': _("This account is inactive."),
}
def __init__(self, request=None, *args, **kwargs):
"""
The 'request' parameter is set for custom auth use by subclasses.
The form data comes in via the standard 'data' kwarg.
"""
self.request = request
self.user_cache = None
forms.Form.__init__(self, *args, **kwargs)
# trick the default template into believing username_field is username
self.fields['username'] = self.fields[self.username_field]
# Set the label for the "username" field.
if self.fields['username'].label is None:
self.fields['username'].label = capfirst(self.username_field)
# remove the username_field field since that's not required
del self.fields[self.username_field]
def clean(self):
username_field_value = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username_field_value is not None and password:
self.user_cache = authenticate(self.request, password=password,
**{self.username_field: username_field_value})
if self.user_cache is None:
# An authentication backend may reject inactive users. Check
# if the user exists and is inactive, and raise the 'inactive'
# error if so.
try:
self.user_cache = UserModel._default_manager.get(**{self.username_field: username_field_value})
except UserModel.DoesNotExist:
raise forms.ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={'username_field': self.fields['username'].label},
)
else:
self.confirm_login_allowed(self.user_cache)
raise forms.ValidationError(
self.error_messages['wrong_password'],
code='wrong_password',
)
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
## EXAMPLE USAGE
class EmailAuthenticationForm(DynamicAuthenticationForm):
username_field = 'email'
email = forms.EmailField()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment