見出し画像

DRF_Django標準の機能でユーザー登録を実装する #177日目

本日はDjangoの標準機能を使って、超簡単なユーザー登録画面を作りたいと思います。以下のようなアプリが完成します。

最期の画像の右上が、登録したユーザー名になっている点がポイントです。つまり、登録後にそのままログインする形をとっています。

ユーザーのデータが蓄積されていくモデルはDjangoが標準で用意してくれているので、自分でマイグレーションする必要はありません。管理画面に入るために管理ユーザーを作ったりすると思いますが、その時にも標準のユーザー用モデルにデータが格納されています。


ではまず肝心のビューから作成します。ユーザー登録に必要なフォームはUserCreationFromを使います。

[apiv1/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"]
            # ユーザーを認証する
            new_user = authenticate(username=input_username, password=input_password)
            if new_user is not None:
                # ユーザーをログイン状態にする
                login(request, new_user)
                return redirect("http://localhost:8000/api/v1")
    else:
        form = UserCreationForm()
    return render(request, "signup.html", {"form": form})

登録成功時には、そのままユーザー名とパスワードを認証にかけ、ログインするようにしています。リダイレクト先は絶対パスで指定していて、「api/v1」というページです(冒頭の最後の画像)。

続いてURLConfですが、これは今回はあまり考えずに普通に設定しています。

[apiv1/urls.py]
 
from django.urls import path
from . import views

urlpatterns = [
    path('signup/', views.signup, name="signup"),
]

最後にhtmlですが、これは作成中のAPIアプリを踏襲しつつ、うまく表示されない部分を微調整しています。

[templates/signup.html]
 
<!DOCTYPE html>
{% load static %}

<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"/>
        <title>DRF Sample</title>
        <!--CSS-->
        <!--BootstrapVue-->
        <link rel="stylesheet" href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css"/>
        <link rel="stylesheet" href="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.min.css"/>
        <style>
            main.container {
                border: 1px solid #cccccc;
                width: 600px;
            }
            [v-cloak] {
                display: none;
            }
        </style>
    </head>
    <body>
    <div id="app">
        <!--ヘッダナビゲーション-->
        <div id="header">
            <navbar type="dark" variant="dark">
                <a class="navbar-brand" href="/">DRF Sample</a>
                <navbar-nav class="ml-auto">
                    {% if user.is_authenticated %}
                    <nav-item-dropdown right>
                        <template slot="button-content">{{ user.get_username }}</template>
                        <dropdown-item href="{% url 'rest_framework:logout' %}">
                            ユーザー登録済みです
                        </dropdown-item>
                    </nav-item-dropdown>
                    {% else %}
                    <nav-item href="{% url 'rest_framework:login' %}">
                        ユーザー登録してください
                    </nav-item>
                    {% endif %}
                </navbar-nav>
            </navbar>
        </div>

        <!--メインエリア-->
        <div id="main-page">
            <main class="container mt-5 p-5">
                <p class="h5 mb-5">ユーザー登録</p>
                <form method="POST" action="{% url 'apiv1:signup' %}">
                    {% csrf_token %}
                    <div class="row form-group">
                        <label class="col-sm-4 col-form-label">ユーザー名</label>
                        <div class="col-sm-8">
                            {{ form.username }}
                            {{ form.username.errors }}
                        </div>
                    </div>
                    <div class="row form-group">
                        <label class="col-sm-4 col-form-label">パスワード</label>
                        <div class="col-sm-8">
                            {{ form.password1 }}
                            {{ form.password1.errors }}
                        </div>
                    </div>
                    <div class="row form-group">
                        <label class="col-sm-4 col-form-label">パスワード(確認)</label>
                        <div class="col-sm-8">
                            {{ form.password2 }}
                            {{ form.password2.errors }}
                        </div>
                    </div>
                    <div class="row text-center mt-5">
                        <div class="col-sm-12">
                            <button type="submit" class="btn btn-primary">登録</button>
                        </div>
                    </div>
                </form>
            </main>
        </div>
    </div>
    
        <!--JS-->
        <!--Vue & BootstrapVue-->
        <script src="https://unpkg.com/babel-polyfill@6.26.0/dist/polyfill.min.js"></script>
        <script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
        <script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.min.js">
        </script>


    </body>
</html>


ここまでお読みいただきありがとうございました!!


参考


この記事が気に入ったらサポートをしてみませんか?