Opened 12 years ago
Closed 12 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
ModelBackendthe next lines do this:try: user = UserModel._default_manager.get_by_natural_key(username)and the
get_by_natural_keymethod will now make use ofUSERNAME_FIELDlike it should do.