LoginSignup
20
22

More than 5 years have passed since last update.

Webアプリ開発実践:Djangoでシフト作成ページを作ろう!(認証系の処理)

Posted at

前回の投稿からだいぶ間が空いてしまいましたが続きをやっていこうと思います。

実は作業自体は結構勝手に進めてしまっていてただ単に投稿をしていなかった感じなので、今回からはそれらを少しずつ小出しにしていくとしましょう。

まずは軽めに、認証系の処理から。自分がやった過去の投稿を参考にして実装。

owner/views.py
from django.shortcuts import render,redirect
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.decorators import login_required


def log_in(req):

    if req.user.is_authenticated():
        return redirect('/')  # 認証されていたらトップページ(今回は触れないが)にリダイレクト

    error_msg = ""  # エラーメッセージを定義してテンプレートに持っていく

    if req.method == 'POST':
        posted = req.POST
        name,password = posted['name'],posted['password']

        user = authenticate(username=name,password=password)

        if user is not None:
            if user.is_active:
                login(req,user)

                return redirect('/')
            else:
                error_msg = "This account is not active..."
        else:
            error_msg = "Log in failed...."

    return render(req,'owner/log_in.html',{'error_msg':error_msg}) 


def log_out(req):
    logout(req)

    return redirect('/login/')  # ログアウトしたらログイン画面に戻る


def new_owner(req):  # 新しいUserを作るページ。シフトの所有者なのでownerとしている

    error_msg = ""

    if req.method == 'POST':
        posted = req.POST
        name,password = posted['name'],posted['password']

        if password != posted['pass_check']:  # よくあるように2回入力してパスワードをチェック
            error_msg = "Password check is failed!"
        else:
            if len(password) < 6:  # パスワードは6文字以上にしとく
                error_msg = "Password need over 6 letters!"
            else:
                from django.db import IntegrityError
                from django.contrib.auth.models import User
                try:
                    owner = User.objects.create_user(username=name,password=password)
                    return redirect('/')
                except IntegrityError:  # ユーザー名が既に使われているとこのエラーを吐くので対策
                    error_msg = "You can not use this name!"

    return render(req,'owner/new_owner.html',{'error_msg':error_msg,})


@login_required  # 要ログインにするための便利なデコレータ(settingsにLOGIN_URLを設定しておく必要がある。あとはそのURLに自分のログインページを置けばOK)
def edit_groupschedule(req):  # シフトの設定を決める感じなのでshiftsettingとしたほうが分かりやすいかも
    from django.contrib.auth.models import Group
    from owner.models import GroupSchedule

    try:  # アクセスしたユーザーがまだGroupScheduleを持っていなかったら新規作成、すでに持っていたら編集という風に動的にしてみた
        groupschedule = GroupSchedule.objects.get(owner=req.user)
        group = groupschedule.group
    except GroupSchedule.DoesNotExist:
        groupschedule = GroupSchedule(owner=req.user)
        group = Group()

    if req.method == 'POST':
        posted = req.POST

        group.name = posted['name']
        group.save()

        groupschedule.group = group
        groupschedule.start_point = int(posted['start_point'])
        groupschedule.save()

        return redirect('/')  # セーブしたらトップへジャンプ

    return render(req,'owner/edit_groupschedule.html',{
        'group_name':group.name,
        'start_point':groupschedule.start_point,
        'select_choices':(1,5,10,15,20,25,),  # 毎月のシフト開始日の候補
    })

次はテンプレート。Bootstrapを使用しているのですがフォームの部品を作る度に<div>を書いたりするのはちょっと面倒くさいので、繰り返し使いそうな部品はそれぞれの templates/app 以下に parts というディレクトリを作って置いおきます。あとは include というテンプレートタグを使えばそれを引っ張ってくることが出来ます。 extendsは土台で、includeは部品 というイメージか。

例えばこんな感じ。

parts/input.html
<div class="form-group">
    <label>{{ label }}
        <input type="{{ type }}" name="{{ name }}" class="form-control {{ class }}" value="{{ value }}">
    </label>
</div>

あとは適当に作っていくといい。それぞれの変数の中には部品を読み込む際に値を入れることが出来るのでクラスを足したりすることも可能。さらに、これをベースにしてアプリケーション用の部品を作製したのでそれを使う。

templates/owner/log_in.html
{% extends 'bases/base_form.html' %}

{% block title %}Log in{% endblock %}

{% block form %}
<h1>Log in<small>{{ error_msg }}</small></h1>  <!--エラーがあればメッセージ表示-->
    {% include 'owner/parts/name_input.html' %}
    {% include 'owner/parts/pass_input.html' %}

    {% include 'parts/submit.html' with class='btn-lg btn-primary' value='Log in!' %}  {# withで変数に値を入れることができる #}
    <a href="/owner/new">Create New User</a>
{% endblock form %}

あとは大体同じ。

..../new_user.html
{% extends 'owner/bases/base_form.html' %}

{% block title %}new Owner!{% endblock %}

{% block form %}
<h1>new Owner!<small>{{ error_msg }}</small></h1>
    {% include 'owner/parts/name_input.html' %}
    {% include 'owner/parts/pass_input.html' %}
    {% include 'owner/parts/pass_input2.html' %}

    {% include 'parts/submit.html' with value="Create new owner!" %}
{% endblock form %}
..../edit_groupschedule.html
{% extends 'owner/bases/base_form.html' %}

{% block title %}new Schedule!{% endblock %}

{% block form %}
    {% include 'owner/parts/name_input.html' with value=group_name %}  {# 初期値。views.pyから持ってきた変数をさらに部品に渡す感じ #}
    {% include 'owner/parts/select_number.html' with start_point=start_point select_choices=select_choices %}  {# 選択候補 #}
    {% include 'owner/parts/submit.html' with value='Create your Schedule!' %}
{% endblock form %}

どうでもいいといえばどうでもいいですが、ブランクを空けてみて自分のコードがいかに分かりづらいかを実感しました(クラスとか関数名も意味が通らないものがあるし)。それが恥ずかしいから投稿する気もあまり起こらず、「まあいいや」と思って自分だけで進めていたらますます散らかっていくという悪循環。
とりあえずやったところまでは投稿していこうと思いますが、もういっそゼロから作り直したほうが気持ちよく書いていけそうな気がする。

20
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
22