I use Django 5 and django-allauth. Currently I do not use any advanced features of this library, the only reasons I use it:
- It has a well-developed workflow with email opt-in feature
- It can support both username and email based authentication out of the box.
Here is my settings, related to the library:
# django-allauth specific settings for regular accounts not including the social authentication part.
ACCOUNT_AUTHENTICATION_METHOD="username_email"
ACCOUNT_CHANGE_EMAIL=True
ACCOUNT_CONFIRM_EMAIL_ON_GET=False
ACCOUNT_EMAIL_REQUIRED=True
ACCOUNT_EMAIL_VERIFICATION="mandatory"
ACCOUNT_UNIQUE_EMAIL=True
ACCOUNT_DEFAULT_HTTP_PROTOCOL="https"
ACCOUNT_MAX_EMAIL_ADDRESSES=2
ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE=True
ACCOUNT_LOGIN_ON_PASSWORD_RESET=True
ACCOUNT_SESSION_REMEMBER=True
ACCOUNT_USERNAME_REQUIRED=False
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE=False
# Our specific signup and login forms with special styling
ACCOUNT_FORMS = {'signup': 'user_profile.forms.CustomSignupForm',
'login': 'user_profile.forms.CustomLoginForm'}
The only role of CustomLoginForm is to have customized css:
from allauth.account.forms import LoginForm
class CustomLoginForm(LoginForm):
def __init__(self,*args, **kwargs):
super().__init__(*args, **kwargs)
# The parent class does similar. The only reason we had to make custom loginform
# to handle bootstrap css
self.fields["login"].widget.attrs.update({"class": TEXT_INPUT_CLASS})
if app_settings.AuthenticationMethod == AuthenticationMethod.USERNAME:
self.fields["login"].widget.attrs.update({"placeholder": "Felhasználónév",
"autocomplete": "username"})
elif app_settings.AuthenticationMethod == AuthenticationMethod.EMAIL:
self.fields["login"].widget.attrs.update({"placeholder": "Email cím",
"autocomplete": "email"})
else:
self.fields["login"].widget.attrs.update({"placeholder": "Email cím / felhasználónév",
"autocomplete": "email"})
self.fields["password"].widget.attrs.update({"class": TEXT_INPUT_CLASS,
"placeholder": "Add meg a jelszavad",
"autocomplete": "password"})
When I start my development server to see why I can not login with existing username and password, I used the Debug Toolbar to see SQLSs generated by the ORM:
SELECT "auth_user"."id",
"auth_user"."password",
"auth_user"."last_login",
"auth_user"."is_superuser",
"auth_user"."username",
"auth_user"."first_name",
"auth_user"."last_name",
"auth_user"."email",
"auth_user"."is_staff",
"auth_user"."is_active",
"auth_user"."date_joined"
FROM "auth_user"
WHERE "auth_user"."username" = '''[email protected]'''
LIMIT 21
SELECT "account_emailaddress"."id",
"account_emailaddress"."user_id",
"account_emailaddress"."email",
"account_emailaddress"."verified",
"account_emailaddress"."primary"
FROM "account_emailaddress"
WHERE "account_emailaddress"."email" LIKE '''[email protected]''' ESCAPE '\'
SELECT "auth_user"."id",
"auth_user"."password",
"auth_user"."last_login",
"auth_user"."is_superuser",
"auth_user"."username",
"auth_user"."first_name",
"auth_user"."last_name",
"auth_user"."email",
"auth_user"."is_staff",
"auth_user"."is_active",
"auth_user"."date_joined"
FROM "auth_user"
WHERE "auth_user"."id" IN ('4')
SELECT "auth_user"."id",
"auth_user"."password",
"auth_user"."last_login",
"auth_user"."is_superuser",
"auth_user"."username",
"auth_user"."first_name",
"auth_user"."last_name",
"auth_user"."email",
"auth_user"."is_staff",
"auth_user"."is_active",
"auth_user"."date_joined"
FROM "auth_user"
WHERE "auth_user"."username" LIKE '''[email protected]''' ESCAPE '\'
LIMIT 21
Since users can login by username or email, it's reasonable to see multiple queries. The one thing I do not understand is why string literals in the where conditions are surrounded by 4 additional quotation marks?
If I eliminate the redundant quotation marks, the query gives back the matchd user in Sqlite browser. If I do not remove the redundant quotation marks, it does not.
Whcih code puts the extra quotation marks and why? How can I fix this?