【Django】通过几分钟即可实现的用户注册和登录功能
首先
目标
在这篇文章中,我们将介绍如何使用Django框架快速实现用户注册和登录功能!通过这种方法,您可以在Web应用程序开发中高效地实现繁琐的认证功能。
这篇文章的主要目的是解释如何使用Django快速实现用户注册和登录功能。
这篇文章适合对Django感兴趣并准备开始学习的初学者?♂️。
关于Django框架
Django是一个由Python开发的开源Web应用程序框架。Django已经内置了许多有用的功能。因此,开发者可以摆脱繁琐的基本功能实现,专注于应用功能的开发,这也是它的本质目的。
在Django中,已经准备好了用户认证和安全功能等重要元素,你可以通过使用插件和扩展功能来进一步增强功能。因此,即使是初学者也能相对容易地开发安全的Web应用程序。
那么,现在我们就来试试用Django实现用户注册和登录功能吧!
实践
供参考,本次介绍的源代码已在GitHub上公开!
以下是Django文件的内容。
搭建开发环境
-
- OS: macOS 13.2.1
-
- Python: 3.10.3
- Django: 4.1.7
创建和配置Django项目
首先,我们将为这个项目创建一个虚拟环境。
% python -m venv venv
我要进入虚拟环境。
% source venv/bin/activate
我将安装Django。
(venv)% pip install --upgade pip
(venv)% pip install Django
我要创建一个Django项目。
(venv)% django-admin startproject project .
我将编辑settings.py文件。
...
ALLOWED_HOSTS = ['*']
...
让我们启动开发用服务器吧。
(venv)% python manage.py runserver

创建自定义用户
在Django框架中,建议创建自定义的用户模型而不是使用Django的默认用户模型。
在Django应用程序开发的早期阶段创建自定义用户模型可以带来一些好处,例如在以后想要为用户添加年龄或地址等属性时更容易进行修改。
我会创建一个名为”accounts”的应用程序。
(venv)% python manage.py startapp accounts
在settings.py的INSTALLED_APPS中添加accounts。
此外,为了将即将创建的自定义用户用作认证用户模型,将其配置添加进去。
...
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts' # 追加
]
AUTH_USER_MODEL = "accounts.User" # カスタムユーザーを認証用ユーザーとして登録
...
创建自定义用户模型。
from django.db import models
from django.contrib.auth.models import (BaseUserManager,
AbstractBaseUser,
PermissionsMixin)
from django.utils.translation import gettext_lazy as _
class UserManager(BaseUserManager):
def _create_user(self, email, account_id, password, **extra_fields):
email = self.normalize_email(email)
user = self.model(email=email, account_id=account_id, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, account_id, password=None, **extra_fields):
extra_fields.setdefault('is_active', True)
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(
email=email,
account_id=account_id,
password=password,
**extra_fields,
)
def create_superuser(self, email, account_id, password, **extra_fields):
extra_fields['is_active'] = True
extra_fields['is_staff'] = True
extra_fields['is_superuser'] = True
return self._create_user(
email=email,
account_id=account_id,
password=password,
**extra_fields,
)
class User(AbstractBaseUser, PermissionsMixin):
account_id = models.CharField(
verbose_name=_("account_id"),
unique=True,
max_length=10
)
email = models.EmailField(
verbose_name=_("email"),
unique=True
)
first_name = models.CharField(
verbose_name=_("first_name"),
max_length=150,
null=True,
blank=False
)
last_name = models.CharField(
verbose_name=_("last_name"),
max_length=150,
null=True,
blank=False
)
birth_date = models.DateField(
verbose_name=_("birth_date"),
blank=True,
null=True
)
is_superuser = models.BooleanField(
verbose_name=_("is_superuer"),
default=False
)
is_staff = models.BooleanField(
verbose_name=_('staff status'),
default=False,
)
is_active = models.BooleanField(
verbose_name=_('active'),
default=True,
)
created_at = models.DateTimeField(
verbose_name=_("created_at"),
auto_now_add=True
)
updated_at = models.DateTimeField(
verbose_name=_("updateded_at"),
auto_now=True
)
objects = UserManager()
USERNAME_FIELD = 'account_id' # ログイン時、ユーザー名の代わりにaccount_idを使用
REQUIRED_FIELDS = ['email'] # スーパーユーザー作成時にemailも設定する
def __str__(self):
return self.account_id
让我们在管理界面进行用户注册。
为了能够在管理界面中编辑自定义用户,我们将在admin.py中添加设置。
from django.contrib import admin
from django.contrib.auth.models import Group
from .models import User
admin.site.register(User, UserAdmin) # Userモデルを登録
admin.site.unregister(Group) # Groupモデルは不要のため非表示にします
我要进行迁移。
(venv)% python manage.py makemigrations
(venv)% python mange.py migrate
为了登录到管理界面,我们需要创建一个超级用户。
(venv)% python manage.py createsuperuser
请提供账户ID、邮箱和密码的输入,并输入任意值。
启动开发服务器
(venv)% python manage.py runserver
在浏览器中,访问 http://127.0.0.1:8000/admin,并使用您创建的超级用户账号进行登录。

如果能够完成到这一步,定制用户已成功创建,没有任何问题?♂️
用户注册功能的实施
使用Django的UserCreationForm创建用户注册表单。
请在accounts文件夹下创建forms.py。
from django.contrib.auth.forms import UserCreationForm
from .models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields = (
"account_id",
"email",
"first_name",
"last_name",
"birth_date",
)
接下来,创建视图。
from django.contrib.auth import login, authenticate
from django.views.generic import TemplateView, CreateView
from django.urls import reverse_lazy
from .forms import SignUpForm
class IndexView(TemplateView):
""" ホームビュー """
template_name = "index.html"
class SignupView(CreateView):
""" ユーザー登録用ビュー """
form_class = SignUpForm # 作成した登録用フォームを設定
template_name = "accounts/signup.html"
success_url = reverse_lazy("accounts:index") # ユーザー作成後のリダイレクト先ページ
def form_valid(self, form):
# ユーザー作成後にそのままログイン状態にする設定
response = super().form_valid(form)
account_id = form.cleaned_data.get("account_id")
password = form.cleaned_data.get("password1")
user = authenticate(account_id=account_id, password=password)
login(self.request, user)
return response
我将创建一个模板。
在manage.py的同一级目录下创建一个templates文件夹,并将模板文件放置其中。
由于本文关注用户注册和登录功能,因此UI设计仅仅轻量地使用了Bootstrap?♂️
将创建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.0">
<!-- Bootstrap5のCDNを設定 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
<title>Account</title>
</head>
<body>
<div class="container mx-auto text-center">
{% block title %}
{% endblock %}
{% block content %}
{% endblock %}
</div>
</body>
</html>
创建index.html文件。
{% extends 'base.html' %}
{% block title %}
{% if user.is_authenticated %}
<div class="h1">MyPage</div>
{% else %}
<div class="h1">Main</div>
{% endif %}
{% endblock %}
{% block content %}
{% if user.is_authenticated %}
<div class="h2">Welcome {{ user.first_name }} {{ user.last_name }}</div>
{% else %}
<a href="{% url 'accounts:signup' %}" class="btn btn-primary">Signup</a>
{% endif %}
{% endblock %}
这次,我们将根据登录与否来实现顶部页面显示内容的不同。
具体来说,将会显示以下内容。
现在我们将创建一个重要的用户注册表单模板。
{% extends 'base.html' %}
{% block title %}
<div class="h1">Create account</div>
{% endblock %}
{% block content %}
<div>
<br>
<form method="POST">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
{{ field.label }}
{{ field }}
{{ field.errors }}
<br>
{% endfor %}
<div class="mt-3">
<button type="submit" class="btn btn-primary">Create</button>
<a href="{% url 'accounts:index' %}" class="btn btn-secondary">Back</a>
</div>
</form>
</div>
{% endblock %}
我們將對出現在這裡的模板標籤進行解釋。
{% csrf_token %}
CSRF(Cross-Site Request Forgery)対策として使用されます。フォームを使ったPOSTリクエストを送信する際に、このタグを使ってCSRFトークンを自動的に生成し、フォーム内に埋め込むことができます。このトークンを使用することで、不正なPOSTリクエストを防ぐことができます。デフォルトでは、このタグを付けずにPOSTリクエストを行った場合エラーが発生します。
{{ form.non_field_errors }}
フォーム全体に関連するエラーメッセージを表示するための変数です。例えば、フォーム内の2つのフィールド間の関係に問題がある場合や、全体的なバリデーションエラーが発生した場合に、この変数を使ってエラーメッセージを表示することができます。
{% for field in form %} {% endfor %}
Djangoテンプレートタグのforループ構文です。この構文を使用することで、フォーム内のすべてのフィールドを繰り返し処理し、それぞれのフィールドに対してHTMLを生成することができます。
{{ field.label }}
フィールド名を表示するタグ
{{ field }}
フィールドの入力フォーム(ウィジェット)を表示するためのタグです
{{ field.errors }}
任意のフィールドに関連するエラーメッセージを表示するための変数
在settings.py中设置模板文件放置的目录位置。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], # 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',
],
},
},
]
为了能够从浏览器中操作注册表单,我们将创建一个路由。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include("accounts.urls")) # accounts.urls.pyを読み込むための設定を追加
]
在accounts目录中新建一个urls.py文件,并写入配置信息。
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path('signup/', views.SignupView.as_view(), name="signup"),
]
如果能做到这一点,让我们尝试验证已创建用户注册表单的操作!
启动开发服务器,并在浏览器中访问http://127.0.0.1:8000,确认是否显示主页。

主页已经显示出来了!
点击”注册”按钮,我们将从”创建账户”页面开始创建一个账户。

在表格中输入用户信息,并点击”创建”按钮。(在这里,出生日期可以留空。)

用户创建后,身份验证也通过了,MyPage页面就会显示出来?♂️。现在,用户注册功能已经完成了!
实现登录功能
我们来实现登录功能!我们将创建一个登录用的表单。
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm # 追加
from .models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields = (
"account_id",
"email",
"first_name",
"last_name",
"birth_date",
)
# ログインフォームを追加
class LoginFrom(AuthenticationForm):
class Meta:
model = User
创建一个LoginView。
from django.contrib.auth import login, authenticate
from django.views.generic import TemplateView, CreateView
from django.contrib.auth.views import LoginView as BaseLoginView
from django.urls import reverse_lazy
from .forms import SignUpForm, LoginFrom # ログインフォームをimport
class IndexView(TemplateView):
template_name = "index.html"
class SignupView(CreateView):
form_class = SignUpForm
template_name = "accounts/signup.html"
success_url = reverse_lazy("accounts:index")
def form_valid(self, form):
# login after signup
response = super().form_valid(form)
account_id = form.cleaned_data.get("account_id")
password = form.cleaned_data.get("password1")
user = authenticate(account_id=account_id, password=password)
login(self.request, user)
return response
# ログインビューを作成
class LoginView(BaseLoginView):
form_class = LoginFrom
template_name = "accounts/login.html"
我将创建登录模板。
{% extends 'base.html' %}
{% block title %}
<div class="h1">Login</div>
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
{{ field.label }}
{{ field }}
{{ field.errors }}
<br>
{% endfor %}
<div class="mt-3">
<button type="submit" class="btn btn-primary">Login</button>
<a href="{% url 'accounts:index' %}" class="btn btn-secondary">Back</a>
</div>
</form>
{% endblock %}
设置登录页面的URL。
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path('signup/', views.SignupView.as_view(), name="signup"),
path('login/', views.LoginView.as_view(), name="login"),
]
在登录后重定向的URL,将其设置在settings.py中。
...
LOGIN_REDIRECT_URL = "accounts:index"
通过这个,登录后会自动跳转到首页。
实现登出功能
我們將實施登出功能。
在views.py中创建一个LogoutView。
from django.contrib.auth import login, authenticate
from django.views.generic import TemplateView, CreateView
from django.contrib.auth.views import LoginView as BaseLoginView, LogoutView as BaseLogoutView
from django.urls import reverse_lazy
from .forms import SignUpForm, LoginFrom
class IndexView(TemplateView):
template_name = "index.html"
class SignupView(CreateView):
form_class = SignUpForm
template_name = "accounts/signup.html"
success_url = reverse_lazy("accounts:index")
def form_valid(self, form):
# login after signup
response = super().form_valid(form)
account_id = form.cleaned_data.get("account_id")
password = form.cleaned_data.get("password1")
user = authenticate(account_id=account_id, password=password)
login(self.request, user)
return response
class LoginView(BaseLoginView):
form_class = LoginFrom
template_name = "accounts/login.html"
# LogoutViewを追加
class LogoutView(BaseLogoutView):
success_url = reverse_lazy("accounts:index")
我們將在urls.py文件中設置logout的路徑。
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
path("", views.IndexView.as_view(), name="index"),
path('signup/', views.SignupView.as_view(), name="signup"),
path('login/', views.LoginView.as_view(), name="login"),
path('logout/', views.LogoutView.as_view(), name="logout"), # 追加
]
在模板中添加登出按钮。
{% extends 'base.html' %}
{% block title %}
{% if user.is_authenticated %}
<div class="h1">MyPage</div>
{% else %}
<div class="h1">Main</div>
{% endif %}
{% endblock %}
{% block content %}
{% if user.is_authenticated %}
<div class="h2">Welcome {{ user.first_name }} {{ user.last_name }}</div>
<!-- ↓追加 -->
<a href="{% url 'accounts:logout' %}" class="btn btn-primary">Logout</a>
{% else %}
<a href="{% url 'accounts:signup' %}" class="btn btn-primary">Signup</a>
<a href="{% url 'accounts:login' %}" class="btn btn-primary">Login</a>
{% endif %}
{% endblock %}
在settings.py中设置登出后的重定向URL。这次我们设置为跳转到登录页面。
...
LOGIN_REDIRECT_URL = "accounts:index"
LOGOUT_REDIRECT_URL = "accounts:login"
通过在我的页面上点击“Logout”按钮即可进行登出操作。
登录和注销操作的确认
用户创建后处于登录状态,首先点击注销按钮,然后进行注销。




总结
由于Django内置了认证功能,我们可以轻松实现用户注册和登录功能!
这篇文章是为那些急于学习Django认证功能的人准备的推荐文章,接下来我们还会介绍表单定制等内容,敬请期待?