Hello!
User authentication has long been a common task. In Django, as in any modern web framework, there is an excellent user authentication mechanism.
However, this mechanism by default uses the login as an identifier, while all of us are accustomed to using email to log in.
When I needed to implement this functionality, it turned out that there are not so many tutorials, especially in Russian, which describe how to register by email, send a verification email, reset the password, and other things that are generally quite normal.
I decided to correct this injustice.
Having rummaged a little on the Internet, my choice fell on the django-user-accounts module.
This module is part of the Pinax ecosystem, has good documentation and, best of all, some easy-to-read code.
Module can:
To install, execute the command:
pip install django-user-accounts
Do not forget to add the dependency to the requirements.txt file:
django-user-accounts==2.0.3
In settings.py add INSTALLED_APPS:
INSTALLED_APPS =[ ..... 'django.contrib.sites', 'account' ]
It is important to add a standard jung site module, since the account depends on it.
Next add MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = [ ..... 'account.middleware.LocaleMiddleware', 'account.middleware.TimezoneMiddleware' ]
And context_processors:
TEMPLATES = [ { ..... 'OPTIONS': { 'context_processors': [ ..... 'account.context_processors.account' ], }, }, ]
In order for us to have a unique email and to require confirmation, we will add two keys in settings.py:
ACCOUNT_EMAIL_UNIQUE = True ACCOUNT_EMAIL_CONFIRMATION_REQUIRED = True
Now you can migrate:
python manage.py migrate
As a result, new tables will appear in the database:
account_account account_accountdeletion account_emailaddress account_emailconfirmation account_passwordexpiry account_passwordhistory account_signupcode account_signupcoderesult django_site
If you have not previously had a connected site module, then you need to create a website:
python manage.py shell >>> from django.contrib.sites.models import Site >>> site = Site(domain='localhost:8000', name='localhost:8000') >>> site.save() >>> site.id 2
And add in the setting.py id of the new site:
SITE_ID = 2
All templates for the necessary pages and texts of letters can be downloaded from pinax-theme-bootstrap and simply put them at yourproject / yourapp / templates / account.
If you are going to connect this module at the level of a Django application, and not a project, then for correct routing, add the following lines in settings.py:
ACCOUNT_LOGIN_URL = 'yourapp:account_login' ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL = ACCOUNT_LOGIN_URL ACCOUNT_PASSWORD_RESET_REDIRECT_URL = ACCOUNT_LOGIN_URL ACCOUNT_EMAIL_CONFIRMATION_URL = "yourapp:account_confirm_email" ACCOUNT_SETTINGS_REDIRECT_URL = 'yourapp:account_settings' ACCOUNT_PASSWORD_CHANGE_REDIRECT_URL = "yourapp:account_password"
And add URLs to the file yourapp / urls.py:
urlpatterns = [ ..... url(r"^account/", include("account.urls")), ..... ]
The following addresses are now available:
account/signup/ account/login/ account/logout/ account/confirm_email/<key> account/password/ account/password/reset/ account/password/reset/<token> account/settings/ account/delete/
It remains only to add the settings for the mail server in settings.py:
DEFAULT_FROM_EMAIL = 'support@yoursite.ru' EMAIL_HOST = "smtp.yoursmtpserver.ru" EMAIL_PORT = 25 EMAIL_HOST_USER = "user" EMAIL_HOST_PASSWORD = "pass"
If you have done everything correctly, then you can log in with the specified username / password, and when you create your account, you will receive an email to confirm your email.
A bug was found that does not allow you to correctly form a link to recover a password if you added links to the application, and not to the project.
Until the pull request is accepted, you can drive a crutch into yourproject / urls.py
from account.views import PasswordResetTokenView urlpatterns = [ ..... url(r"^account/password/reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$", PasswordResetTokenView.as_view(), name="account_password_reset_token"), ..... ]
A new setting will appear in the pull request:
ACCOUNT_PASSWORD_RESET_TOKEN_URL = 'yourapp:account_password_reset_token'
First, add the appropriate backend in settings.py:
AUTHENTICATION_BACKENDS = [ 'account.auth_backends.EmailAuthenticationBackend', ]
Then remove the username from the registration form. To do this, add the following to the file yourapp / forms.py:
import account.forms class SignupForm(account.forms.SignupForm): def __init__(self, *args, **kwargs): super(SignupForm, self).__init__(*args, **kwargs) del self.fields["username"]
And in the file yourapp / views.py it is:
import yourapp.forms import account.forms import account.views class LoginView(account.views.LoginView): form_class = account.forms.LoginEmailForm class SignupView(account.views.SignupView): form_class = yourapp.forms.SignupForm def generate_username(self, form): username = form.cleaned_data["email"] return username def after_signup(self, form): # do something super(SignupView, self).after_signup(form)
Here we set the form classes for views: LoginEmailForm and our SignupForm, respectively, as well as override the after_signup method so that we can mix in any behavior we need. By default, the username field is set to email.
It remains only to override our url in the file yourapp / urls.py:
from . import views urlpatterns = [ ..... url(r"^account/login/$", views.LoginView.as_view(), name="account_login"), url(r"^account/signup/$", views.SignupView.as_view(), name="account_signup"), url(r"^account/", include("account.urls")), ..... ]
I pay attention that the call of custom views must go before connecting account.urls, otherwise they will not be redefined.
In order for current users to log in, you need to add their email addresses to the account_emailaddress table:
insert into account_emailaddress(email, verified, "primary", user_id) select au.email, True, True, au.id from auth_user au where au.email is not null
In this case, true is inserted in the field verified, i.e. we confirm them immediately.
In order for all users to have an account, fill in the account_account table:
insert into account_account (timezone, "language", user_id) select '','ru', id from auth_user
You can learn more about the django-user-account module in the official documentation .
The source code is here . It is useful to read it in order to understand a little better how the auth mechanism works in Django.
I hope this article will save you time. Please share in the comments what tools you use.
Source: https://habr.com/ru/post/341704/
All Articles