My User model has an email field and a username field. `USERNAME_FIELD' is set to email. But I wrote an authentication backend to also support logging in using username:
class UsernameAuthBackend(BaseBackend):
def authenticate(self, request, email=None, password=None):
try:
user = User.objects.get(username=email)
if user.check_password(password):
return user
return None
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
settings.py:
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"accounts.authentication.UsernameAuthBackend",
]
This works fine but it I can't use usernames with obtain_auth_token to get a user's token. (It also doesn't work on Django's admin panel.)
DRF
You can overriding the serializer can provide a cleaner way to adjust the authentication data input for
obtain_auth_token. This is because the actual authentication logic is often handled within the serializer.Here's how you can create a custom serializer to handle both email and username:
CustomObtainAuthTokenView to use the Custom Serializer:This way, you're handling the logic of determining whether the input is a username or email in the serializer's
validatemethod, making the view simpler and more consistent with Django REST framework's patterns.Django Admin
You can use django-username-email package or override the default authentication form to allow for username-based authentication. Here's a basic approach:
Please note that the above code snippets are more conceptual than exact code.