使用Django和django-allauth以及CustomUser创建认证功能

首先

我想要使用django-allauth和CustomUser进行身份验证,但是由于有限的日语文章数量,寻找好的英语文章非常困难,所以我将提供一个示例以及解释一些我遇到的问题和相关代码。

目录

1. 范例 lì)
2. 困惑之处 huò zhī chù)
3. 文件结构 jié
4. url.py (URL.py)
5. settings.py (配置.py)
6. models.py (模型.py)
7. forms.py (表单.py)
8. adapter.py (适配器.py)
9. 模板 (mó
10. 参考

1. 例子

样本代码(Github)

1573995017.jpg

2. 完全上瘾了

ハマったところ
Userとsignupformを拡張して、年齢と体重の項目を追加したが、CustomUserで追加したage,weightに値が入らない。

理由
django-allauthでは、Customuserでuserを、CustomSignupformでsignupformを拡張してもsignupformから入力された値はユーザーフィールドにdefaultで保存されない。

解決法
adapter.pyを作り、AccountAdapterクラスとsave_user関数を記述すると、拡張したフィールドに入力された値がCustomUserに保存できるようになる。

3. 文件结构

试验站点/
├模板/
│    ├账户/
│    │   └注册/
│    │       └登录.html/
│    │       └注册.html/
│   ├测试应用/
│   │   └主页.html
│   └基本.html
├测试应用/
│   ├__pycache__
│   ├迁移
│   ├适配器.py
│   ├管理员.py
│   ├应用程序.py
│   ├表单.py
│   ├模型.py
│   ├测试.py
│   ├URLs.py
│   └视图.py
├试验站点/
│   ├__pycache__
│   ├__init__
│   ├设置.py
│   ├URLs.py
│   └wsgi.py
└manage.py

4. 网址.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. 设置.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/'

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

# 認証方式を「メールアドレスとパスワード」に変更
ACCOUNT_AUTHENTICATION_METHOD = 'email'
# ユーザー名を使用する
ACCOUNT_USERNAME_REQUIRED = True

# ユーザー登録確認メールは送信しない
ACCOUNT_EMAIL_VERIFICATION = 'none'
# メールアドレスを必須項目にする
ACCOUNT_EMAIL_REQUIRED = True

#ユーザーモデルの拡張(customuser)
AUTH_USER_MODEL = 'testapp.CustomUser'

SITE_ID = 1 #django-allauthがsitesフレームワークを使っているため

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

#signupformを指定
ACCOUNT_FORMS = {
    'signup' : 'testapp.forms.CustomSignupForm',
}
#signupformからの情報をcustomusermodelに保存するのに必要
ACCOUNT_ADAPTER = 'testapp.adapter.AccountAdapter'
#passwordの入力を一回に
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False

6.模型.py

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

# Create your models here.
class CustomUser(AbstractUser):
    """拡張ユーザーモデル"""
    class Meta(AbstractUser.Meta):
        db_table = 'custom_user'

    age = models.IntegerField('年齢', blank=True, default=0)
    weight = models.IntegerField('体重',blank=True, default=0)

7. 表格.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 适配器.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个模板

<!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>
<!doctype html>
{% extends "base.html" %}

{% block title %}ログイン{% endblock %}

{% block content %}
<h2>ログイン</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">ログイン</button>
</form>
{% endblock %}
<!doctype html>
{% extends "base.html" %}

{% block title %}ユーザー登録{% endblock %}

{% block content %}
<h2>ユーザー登録</h2>
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <p><a href="{% url 'login' %}"><button type="submit">ユーザー登録</button></a></p>
</form>
{% endblock %}
<!doctype html>
{% extends "base.html" %}

{% block title %}ホーム{% endblock %}

{% block content %}
<h2>ホーム</h2>
{% if user.is_authenticated %}
ようこそ {{ user.get_username }} さん
あなたの年齢は{{ user.age }}です
あなたの体重は{{ user.weight }}kgです
<p><a href="{% url 'logout' %}">ログアウト</a></p>
{% else %}
<p><a href="{% url 'login' %}">ログイン</a></p>
<p><a href="{% url 'signup' %}">signup</a></p>
{% endif %}
{% endblock %}

10. 参考

《现场可用的 Django 教程》作者横瀬明仁
django-allauth 的官方文档1
django-allauth 的官方文档2
完全指南:Django-allauth
扩展和自定义 Django-allauth

bannerAds