このレッスンでは、ユーザー登録機能を実装して、新規ユーザーを作成できるようにします。

登録機能の実装に必要なことは以下の通りです。

  1. 登録画面のURLを設定する。
  2. 登録画面に入力フォーム(UserCreationForm)を表示する。
  3. UserCreationFormから受け取った情報でユーザーを新規作成する。
  4. 作成したユーザーをログイン状態にする。

まずはURLの設定から行いましょう。http://127.0.0.1:8000/signup/で登録フォームを表示するようにします。

~/PhotoService/app/urls.py

from django.urls import path
from . import views
from django.contrib.auth import views as auth_views

app_name = 'app'
urlpatterns = [
    path('', views.index, name='index'),
    path('users/<int:pk>', views.users_detail, name='users_detail'),
    path('signup/', views.signup, name='signup'),  ← 追加
    path('login/', auth_views.LoginView.as_view(template_name='app/login.html'), name='login'),
    path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]    

次に、viewの設定です。

~/PhotoService/app/views.py

from django.contrib.auth.forms import UserCreationForm  # import文を追加

# 追加
def signup(request):
    form = UserCreationForm()
    return render(request, 'app/signup.html', {'form': form})

ユーザー登録用のフォーム(UserCreationForm)をインポートして、signup.htmlに渡します。

signup.htmlを作ります。

~/PhotoService/app/templates/app/signup.html

{% extends 'app/base.html' %}

{% block content %}

<h2>ユーザー登録</h2>

<form method="post" action="{% url 'app:signup' %}">{% csrf_token %}
    <label>ユーザー名</label>
    {{ form.username }}
    {{ form.username.errors }}
    <br>
    <label>パスワード</label>
    {{ form.password1 }}
    {{ form.password1.errors }}
    <br>
    <label>パスワード(確認)</label>
    {{ form.password2 }}
    {{ form.password2.errors }}
    <br>
    <input type="submit" value="登録する">
</form>

<p><a href="{% url 'app:login' %}">ログインはこちら</a></p>

{% endblock %}

これで、http://127.0.0.1:8000/signup/でユーザー登録用のページが表示されるようになりました。

前のレッスンでログイン機能を実装した時は、auth_views.LoginViewがフォームから情報を受け取って自動的にログインを実行しました。ユーザー登録の場合は、自分でviews.pyに登録処理を実装します。views.pyを以下のように編集してください。

~/PhotoService/app/views.py

from django.contrib.auth.forms import UserCreationForm

def signup(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST) # 入力された値からUserインスタンスを作成
        if form.is_valid():
            new_user = form.save() # ユーザーインスタンスを保存
    else:
        form = UserCreationForm()
    return render(request, 'app/signup.html', {'form': form})

UserCreationFormは、新しいユーザーを作成するためのModelFormですので、2つ目のチュートリアルで扱ったModelFormと基本的には同じことをしてくれます。

また、UserCreationFormは入力された値に対して以下のようなチェックを行います。もし入力値が不正であればエラーを表示することができます。

  • password1とpassword2(確認用)の入力値が一致しているかどうか
  • パスワードとしてふさわしい値が入力されているか(短すぎたり、ユーザー名と似すぎていたりするとエラーとなる。)
  • 同名の既存ユーザーが存在していないか

ここまでできたら、実際に登録フォームに値を入力してみましょう。その際、登録ボタンを押してもページ遷移されませんが、ユーザーは作られているはずですので、Admin画面にアクセスして新規ユーザーが本当にできているかを確かめてみましょう。

登録と同時に、ユーザーをログインさせる

現状の実装では「ユーザーを新規作成する」ことはできていますが、登録してもページ遷移がされませんしログインもできていません。実際のWebサービスでは「ユーザー登録完了と同時にログインしてマイページなどに遷移する」のが一般的な流れですので、そのように実装してみましょう。

~/PhotoService/app/views.py

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login  ← 追加

def signup(request):
    if request.method == 'POST':
        form = UserCreationForm(request.POST) # ユーザーインスタンスを作成
        if form.is_valid():
            new_user = form.save() # ユーザーインスタンスを保存
            input_username = form.cleaned_data['username']
            input_password = form.cleaned_data['password1']
            # フォームの入力値で認証できればユーザーオブジェクト、できなければNoneを返す
            new_user = authenticate(username=input_username, password=input_password)
            # 認証成功時のみ、ユーザーをログインさせる
            if new_user is not None:
                # loginメソッドは、認証ができてなくてもログインさせることができる。→上のauthenticateで認証を実行する
                login(request, new_user)
                return redirect('app:users_detail', pk=new_user.pk)
    else:
        form = UserCreationForm()
    return render(request, 'app/signup.html', {'form': form})

cleaned_dataという属性で、formに入力された値を取得して、それぞれ変数に代入しています。

また、ファイル冒頭ではauthenticateloginというメソッドをインポートしています。これを使って、ユーザーの認証を行います。それぞれのメソッドの役割は以下の通りです。

  • authenticate: usernameとpasswordを引数に取り、その組み合わせで認証に成功すればUserオブジェクトを返す。認証できなければNoneを返す。
  • login: リクエスト情報とUserオブジェクトを引数に取り、そのユーザーを未ログイン状態からログイン状態にする。

上記viewの実装では、フォームに入力されたユーザー名(input_username)とパスワード(input_password)の値が、組み合わせとして正しいかをauthenticate(username=input_username, password=input_password)で検証しています。組み合わせが正しければ、authenticateメソッドは認証に成功したUserオブジェクトを返すので、変数new_userにはそのオブジェクトが代入されます。認証に失敗した場合は、new_user=Noneとなります。

そして認証成功時のみ、loginメソッドを実行してユーザーをログイン状態にし、そのユーザーのdetailページにリダイレクトさせます。

※loginメソッド自体は認証機能を備えていないため、その前にauthenticateメソッドで認証を行なっています。(loginメソッドは認証されていないユーザーに対しても使うことができます。つまり、認証なしでユーザーをログインさせることもできますが、基本的にはauthenticateメソッドと併用して認証済みのユーザーだけをログインさせるのが一般的でしょう。)

それでは、再度ユーザー登録をしてみましょう。登録ボタンを押すと、ログイン状態となり、自分のdetailページに遷移するはずです。

< PREV NEXT >
SHARE ! Tweet