Opened 11 years ago
Closed 11 years ago
#20886 closed Bug (invalid)
auth.forms.AuthenticationForm incompatible with auth.backends.ModelBackend when using custom user model
Reported by: | Paul Garner | Owned by: | nobody |
---|---|---|---|
Component: | contrib.auth | Version: | 1.5 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
If you have a custom user model which does not have a field called username
you are supposed to be able to use a different field (eg email
) and specify USERNAME_FIELD = 'email'
on your custom model.
I'm trying to use the built-in login view. It looks fine when I bring up the page, it has recognised my USERNAME_FIELD
and displays 'Email address' as the label.
However I can't login. I have looked into why - it's because there is this code in auth.forms.AuthenticationForm
def clean(self): username = self.cleaned_data.get('username') password = self.cleaned_data.get('password') if username and password: self.user_cache = authenticate(username=username, password=password)
...where username
here is the name of the field on the form and is not wrong. The problem is when it calls authenticate(username=username...
The authenticate
method of ModelBackend
looks like:
def authenticate(self, username=None, password=None, **kwargs): UserModel = get_user_model() if username is None: username = kwargs.get(UserModel.USERNAME_FIELD)
which tries to integrate our custom USERNAME_FIELD
... but we can see we're doing it wrong back in AuthenticationForm
.
Um sorry, my bad. I had saved plaintext into the password field for my test user, which is why authentication was failing.
The code above looked wrong at first glance, but actually it's okay because in
ModelBackend
the next lines do this:and the
get_by_natural_key
method will now make use ofUSERNAME_FIELD
like it should do.