【Django】ユーザ登録ページを作る

 

こんにちは。のっくんです。

 

BootstrapとDjangoを使って以下のようなユーザ登録ページの作り方をご紹介します。

 

・PC

 

・スマホ

 

[speech_bubble type=”ln” subtype=”L1″ icon=”ilust/cat2_1_idea.png” name=”ネコ”]スマホでみた場合は配置が変わってイイ感じにゃー。どうやっているの?[/speech_bubble] [speech_bubble type=”ln” subtype=”L1″ icon=”profile_face.png” name=”のっくん”]Bootstrapのグリッドレイアウトを使っているんだよ。[/speech_bubble]

 

[toc]

 

開発環境は以下の通りです。

  • Python 3.6
  • Django 2.1

フォームを準備

 

フォームと言っても普通の文字入力を受けつけるようなフォームではありません。

 

ユーザ登録の場合は、ユーザ名やパスワードをデータベースに登録したり、入力データが正しいかチェックしたりする必要があります。

 

このあたりを自分で作るのは大変ですが、DjangoのUserCreationFormを継承することで簡単に実装できます。

 

forms.py

from django.contrib.auth.forms import UserCreationForm

# ユーザ作成フォームを継承
class SignUpForm(UserCreationForm):
    username = forms.CharField()
    password1 = forms.CharField(widget=forms.PasswordInput)
    password2 = forms.CharField(widget=forms.PasswordInput)

 

今回は、ユーザ名、パスワード、パスワード確認の3つを用意します。必要であればメールアドレスなどもここで追加できます。

 

全て文字列での入力になるのでCharFieldを使っています。この他にも、EmailFieldやIntegerFieldなど様々なFieldクラスが用意されています。

 

widget=forms.PasswordInputがありますが、これはパスワードを入力したときに

 

パスワード:●●●

 

こんな感じで隠れるようにするためのものです。

 

フォームの準備はこれで終了です。モデルではないのでマイグレーションは必要ありません。

 

パスワード長を設定

 

今回作るのは掲示板サイトなのでそこまでセキュリティは強くなくても良いかと思います。パスワード長は4で設定します。

 

settings.py

AUTH_PASSWORD_VALIDATORS = [
    {
         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 4,
        }
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

 

VALIDATORSというのはパスワードチェック機能のことです。色んなバリデータがありますので整理してみます。

 

  • UserAttributeSimilarityValidator:ユーザ名とパスワードが似ていないかチェックする
  • MinimumLengthValidator:パスワードが最低限の長さかチェックする
  • CommonPasswordValidator:良く使われているパスワードかどうかチェックする
  • NumericPasswordValidator:全て数値でないかチェックする

 

色んなチェックをしてくれるそうですが、あまり厳しくでもアレなので必要ないものはコメントアウトしています。

 

ビューでの処理

 

フォームを処理するビューを書いていきましょう。

 

基本的な処理は以下の通り。

 

  • SignUpFormをインスタンス化してHTMLに渡す
  • フォームの入力内容をチェックしてDBに保存する
  • ユーザをログイン状態にする

 

views.py

def signup(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect(to='/sns/board')
    else:
        form = SignUpForm()
    return render(request, 'sns/signup.html', {'form': form})

 

この例ではリダイレクト先を/sns/board, SignUpFormを使うHTMLファイルをsns/signup.htmlとしています。

 

テンプレート

 

HTML側では、{{ form.as_p }} と記載するとそれだけでフォームが使えます。signup.htmlにブラウザでアクセスしてみると、、

 

 

フォームが表示されましたが、これだけだと英語ですし見た目があまり良くありません。

 

そこでBootstrapを使って装飾してみます。主な処理は以下の通り。

 

  • グリッドレイアウトを使ってラベルとフォームを一定間隔(3:9)で配置する
  • ラベルの後には「必須」バッジをつける
  • フォームの下に確認ボタンを配置する
  • エラーメッセージを表示する

 

signup.html

<div class="container">
    <p></p>
    <h2>ユーザ登録</h2>
    <p>Soccer Talk(サカトク)のユーザ登録をするにはこちらのフォームをご利用ください。</p>
    <p>パスワードは4文字以上にして下さい。</p>
</div>

<div class="py-3">
    <div class="container">
        <!-- フォーム -->
        <form action="{% url 'signup' %}" method="post">

            <!-- ユーザ名 -->
            <div class="form-group row">
                <label for="name" class="col-md-3 col-form-label">
                    ユーザ名 <span class="badge badge-warning">必須</span>
                </label>
                <div class="col-md-9">
                    {% csrf_token %}
                    {{ form.username }}
                </div>
            </div>
            <!-- /ユーザ名 -->

            <!-- パスワード -->
            <div class="form-group row">
                <label for="password" class="col-md-3 col-form-label">
                    パスワード <span class="badge badge-warning">必須</span>
                </label>
                <div class="col-md-9">
                    {% csrf_token %}
                    {{ form.password1 }}
                </div>
            </div>
            <!-- /パスワード -->

            <!-- パスワード確認 -->
            <div class="form-group row">
                <label for="password2" class="col-md-3 col-form-label">
                    パスワードの確認 <span class="badge badge-warning">必須</span>
                </label>
                <div class="col-md-9">
                    {% csrf_token %}
                    {{ form.password2 }}
                </div>
            </div>
            <!-- /パスワード確認 -->

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

            <!-- 確認ボタン -->
            <div class="form-group row justify-content-end">
                <div class="col-md-9">
                    <button type="submit" class="btn btn-primary">登録する</button>
                </div>
            </div>

        </form>
        <!-- /フォーム -->
    </div>
</div>

 

ブラウザでアクセスすると、、

 

 

だいぶそれっぽくなりました。

 

エラー画面

 

エラーメッセージが表示されるか確認してみます。

 

パスワードが違う場合

 

 

パスワードが短い場合

 

 

英語で出力されてますが、まぁこんな感じです。

 

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog