Edited at

djangoで簡単なユーザー登録の実装


Abstract

ログインやログアウトは、Django側で適当なviewを用意してくれているため、実装するのはそれほど大変ではありません。

しかし、ユーザー登録に関しては、サービスやプロダクトによって必要な情報が異なるため、UserCreationFormを使用して少し実装する必要があります。

公式のドキュメントにはそれほど記載がなく、検索をしても書き方が色々あって混乱するため、手元でうまくいった例を残します。

追記: コメントを反映しました。ご指摘ありがとうございます。


Precondition

python: 3.6.5

django:2.0.6

OS: macOS


Implementation

まず、ユーザー登録の際に使うフォームをカスタマイズしないケース。

具体的には、フォームにUserCreationFormをそのまま使う場合のことをさします。

追記:2019/05/04に編集しました。


views.py

from django.contrib.auth import login

from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView

class SignUp(CreateView):
form_class = UserCreationForm
template_name = "accounts/signup.html"
success_url = reverse_lazy('top')

def form_valid(self, form):
user = form.save() # formの情報を保存
login(self.request, user) # 認証
self.object = user
return HttpResponseRedirect(self.get_success_url()) # リダイレクト


公式によると、form_validを編集する方が良いようです。

必須フィールドを増やしたい場合は、UserCreationFormを継承して、少しだけ加工をすると良いです。

例えば、ユーザー名、名前、パスワードを取得したいケースだと


forms.py

from django.contrib.auth.forms import UserCreationForm

class SignUpForm(UserCreationForm):

class Meta:
fields = ('username', 'email', 'password1', 'password2')


こんな感じで書いて、上のform_classをSignUpFormに変えれば完了です。

あとは、urlsを修正しておきましょう。


urls.py

from django.urls import path

urlpatterns = [
path('accounts/signup/', SignUp.as_view(), name='signup')
]



Appendix

実際には、バックエンド側の処理を書いたら、フロント側でも反映していくわけですが、サインナップ時のエラーを表示させる方法も残しておきます。

下記の記載は、公式のドキュメントによせて書いてみます。


base.html

<!DOCTYPE html>

<html lang="ja">
<head>
{% include 'head.html' %}
</head>

<body>
{% block content %}{% endblock %}
</body>
</html>



signup.html

{% extends 'base.html' %}

{% block content %}
<main>
...
...
{# signup処理部分 #}
<form method="post" action="{% url 'signup' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.email.label_tag }}</td>
<td>{{ form.email }}</td>
</tr>
<tr>
<td>{{ form.password1.label_tag }}</td>
<td>{{ form.password1 }}</td>
</tr>
<tr>
<td>{{ form.password2.label_tag }}</td>
<td>{{ form.password2 }}</td>
</tr>
</table>

<input type="submit" value="login" />

{# エラーメッセージを表示 #}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<p>{{ error }}</p>
{% endfor %}
{% endfor %}
{% endif %}
</form>
{% endblock %}



Conclusion

djangoは、認証に関して色々なツールを用意してくれていて、初心者には結構ありがたい。

実用する際には、OAuthなどの対応が必要になるので、その辺りについても調べていきたいです。