[PYTHON] Create an authentication feature with django-allauth and CustomUser in Django

Introduction

I wanted to authenticate using django-allauth and CustomUser, but there were few Japanese articles and it was difficult to find a good English article, so I will post a commentary and a program where I was addicted to sample.

table of contents

1.sample 2. [I was addicted to](# 2 I was addicted to) 3. [File structure](# 3 file structure) 4. url.py 5. settings.py 6. models.py 7. forms.py 8. adapter.py 9. templates 10. [Reference](# 10 reference)

1.sample samplecode(Github)

When I actually move it, it looks like this. 1573995017.jpg

2. I'm addicted to

-** I'm addicted to **
I expanded the User and signup form and added the items of age and weight, but the age and weight added by CustomUser do not have values. -** Reason **
In django-allauth, even if you extend user with Customuser and signupform with CustomSignupform, the value entered from signupform is not saved in the user field by default. -** Solution **
If you create ʻadapter.py and write ʻAccountAdapter class and save_user function, the value entered in the extended field can be saved in CustomUser.

3. File structure

testsite/  ├templates/  │    ├accounts/  │    │   └registration/  │    │       └login.html/  │    │       └signup.html/  │   ├testapp/  │   │   └home.html  │   └base.html  ├testapp/  │   ├__pycache__  │   ├migrations  │   ├adapter.py  │   ├admin.py  │   ├apps.py  │   ├forms.py  │   ├models.py  │   ├tests.py  │   ├urls.py  │   └views.py  ├testsite/  │   ├__pycache__  │   ├__init__  │   ├settings.py  │   ├urls.py  │   └wsgi.py  └manage.py

4.url.py

url.py


from django.contrib import admin
from django.urls import include, path
from django.views.generic import TemplateView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('testapp.urls')),
    path('accounts/', include('allauth.urls')),
    path('accounts/login/', TemplateView.as_view(template_name = 'login.html'), name='login'),
    path('accounts/logout/', TemplateView.as_view(template_name = 'logout.html'), name='logout'),
    path('accounts/signup/', TemplateView.as_view(template_name = 'signup.html'), name='signup'),
]

5.settings.py Customuser, signupform, adapter settings are required.

settings.py


import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SECRET_KEY = ''

DEBUG = True

ALLOWED_HOSTS = ['*']

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'testapp.apps.TestappConfig',#testapp
    'django.contrib.sites', #for djnago-allauth
    'allauth', #for djnago-allauth
    'allauth.account', #for djnago-allauth
    'allauth.socialaccount',#for djnago-allauth
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'testsite.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'testsite.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'

#add to
AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
)

#Changed the authentication method to "email address and password"
ACCOUNT_AUTHENTICATION_METHOD = 'email'
#Use user name
ACCOUNT_USERNAME_REQUIRED = True

#Do not send user registration confirmation email
ACCOUNT_EMAIL_VERIFICATION = 'none'
#Make your email address a required item
ACCOUNT_EMAIL_REQUIRED = True

#User model extension(customuser)
AUTH_USER_MODEL = 'testapp.CustomUser'

SITE_ID = 1 #django-Because allauth uses the sites framework

LOGIN_REDIRECT_URL = 'home'
ACCOUNT_LOGOUT_REDIRECT_URL = '/accounts/login/'
ACCOUNT_LOGOUT_ON_GET = True

#Specify signup form
ACCOUNT_FORMS = {
    'signup' : 'testapp.forms.CustomSignupForm',
}
#Needed to store information from signupform in customusermodel
ACCOUNT_ADAPTER = 'testapp.adapter.AccountAdapter'
#Enter password at once
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False

6.models.py

models.py


from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.
class CustomUser(AbstractUser):
    """Extended user model"""
    class Meta(AbstractUser.Meta):
        db_table = 'custom_user'

    age = models.IntegerField('age', blank=True, default=0)
    weight = models.IntegerField('body weight',blank=True, default=0)

7.forms.py

forms.py


from allauth.account.forms import SignupForm
from django import forms
from .models import CustomUser
from allauth.account.adapter import DefaultAccountAdapter

class CustomSignupForm(SignupForm):
    age = forms.IntegerField()
    weight = forms.IntegerField()
    
    class Meta:
        model = CustomUser

    def signup(self, request,user):
        user.age = self.cleaned_data['age']
        user.weight = self.cleaned_data['weight']
        user.save()
        return user

8.adapter.py

adapter.py


from allauth.account.adapter import DefaultAccountAdapter

class AccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=True):
        """
        This is called when saving user via allauth registration.
        We override this to set additional data on user object.
        """
        # Do not persist the user yet so we pass commit=False
        # (last argument)
        user = super(AccountAdapter, self).save_user(request, user, form, commit=False)
        user.age = form.cleaned_data.get('age')
        user.weight = form.cleaned_data.get('weight')
        user.save()

9.templates

base.html


<!doctype html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>{% block title %}{% endblock %}</title>

    {# --- css --- #}
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
        integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    <style type="text/css">
        body {
            padding-top: 5rem;
        }
    </style>
    {% block extra_css %}{% endblock %}
</head>

<body>
    <main class="container">
        {% block content %}{% endblock %}
    </main>

    {# --- js --- #}
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
        integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous">
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
        integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous">
    </script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
        integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous">
    </script>
    {% block extra_js %}{% endblock %}
</body>

</html>

account/registration/login.html


<!doctype html>
{% extends "base.html" %}

{% block title %}Login{% endblock %}

{% block content %}
<h2>Login</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Login</button>
</form>
{% endblock %}

account/registration/signup.html


<!doctype html>
{% extends "base.html" %}

{% block title %}user registration{% endblock %}

{% block content %}
<h2>user registration</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <p><a href="{% url 'login' %}"><button type="submit">user registration</button></a></p>
</form>
{% endblock %}

testapp/home.html


<!doctype html>
{% extends "base.html" %}

{% block title %}home{% endblock %}

{% block content %}
<h2>home</h2>
{% if user.is_authenticated %}
Welcome{{ user.get_username }}Mr.
How old are you{{ user.age }}is
Your weight{{ user.weight }}kg
<p><a href="{% url 'logout' %}">Log out</a></p>
{% else %}
<p><a href="{% url 'login' %}">Login</a></p>
<p><a href="{% url 'signup' %}">signup</a></p>
{% endif %}
{% endblock %}

10. Reference

[Akihito Yokose "Django textbooks that can be used in the field"](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF % E3% 81% 88% E3% 82% 8B-Django-% E3% 81% AE% E6% 95% 99% E7% A7% 91% E6% 9B% B8% E3% 80% 8A% E5% AE% 9F% E8% B7% B5% E7% B7% A8% E3% 80% 8B-% E6% A8% AA% E7% 80% AC-% E6% 98% 8E% E4% BB% 81-ebook / dp / B07L3DRGBT? Tag = maftracking264432-22 & linkCode = ure & creative = 6339) django-allauth formula 1 django-allauth formula 2 the-complete-django-allauth-guide extending-and-customizing-django-allauth

Recommended Posts

Create an authentication feature with django-allauth and CustomUser in Django
Create an API with Django
I'm trying to create an authentication / authorization process with Django
Create an update screen with Django Updateview
Create an image with characters in python (Japanese)
Create initial settings and staff apps in Django
Implementing authentication in Django REST Framework with djoser
Create Amazon Linux with AWS EC2 and log in
Create APIs around user authentication with Django REST Framework
Dynamically create tables in schema with Django, dynamically generate models
Create an environment with virtualenv
Easily create authentication, user management, and multilingual systems with Flask-AppBuilder
Basic authentication with an encrypted password (.htpasswd) in bottle with python
Create a homepage with django
Minimum Makefile and buildout.cfg to create an environment with buildout
Create a Todo app with Django ① Build an environment with Docker
Create and list Django models
How to create dataframes and mess with elements in pandas
Create an easy-to-use follow model in Django using ManyToManyField through
I tried to create an article in Wiki.js with SQLAlchemy
Create a temporary file with django as a zip file and return it
How to create a heatmap with an arbitrary domain in Python
Create an environment for Django x Apache x mod_wsgi with Vagrant (Ubuntu 16.04)
Firebase Authentication token issuance in Python and token verification with Fast API
reload in django shell with ipython
Load Django modules with an interpreter
HTTPS with Django and Let's Encrypt
Create an Excel file with Python3
Basic authentication and Digest authentication with Flask
Create an age group with pandas
Note: Send an email with Django
GraphQL API with graphene_django in Django
Create a file uploader with Django
Create and read messagepacks in Python
Create a LINE Bot in Django
Implementation of custom user model authentication in Django REST Framework with djoser
Manage multiple types of users with CustomUser in django-allauth (multi type user)
Create and edit spreadsheets in any folder on Google Drive with python
Create a Todo app with Django ④ Implement folder and task creation functions
I want to create an API that returns a model with a recursive relationship in the Django REST Framework
Create an application by classifying with Pygame
Create RESTful APIs with Django Rest Framework
Create an image processing viewer with PySimpleGUI
Passwordless authentication with RDS and IAM (Python)
Browse an existing external database with Django
Quickly create an excel file with Python #python
Create and run embulk config in Jupyter
CentOS 6.4 with Python 2.7.3 with Apache with mod_wsgi and Django
Dealing with "years and months" in Python
Create your first app with Django startproject
[Python] Quickly create an API with Flask
Create an add-in-enabled Excel instance with xlwings
Create an English word app with python
Create and deploy Flask apps in PTVS
Ramen map creation with Scrapy and Django
Create an upgradeable msi file with cx_Freeze
Create a Python image in Django without a dummy image file and test the image upload
Create an API to convert PDF files to TIF images with FastAPI and Docker
Learn the trends of feature words in texts with Jubatus and categorize input texts
Build a data analysis environment that links GitHub authentication and Django with JupyterHub
Send an email with a user other than EMAIL_HOST_USER written in settings in django