Re:ゼロから始める文系プログラマ

未経験がプログラミングを通して人生を変える

【Django】簡単なSNSアプリを開発する④~ログイン機能実装~


スポンサードリンク
 

f:id:ShotaNukumizu_1000:20211205071412p:plain

おはようございます。Shotaです。

今回も、前回と同様にDjangoで簡単なSNSアプリを開発するための方法を解説していきます。

今回はログイン機能を実装していきます。

▼前回の記事はコチラ

shotanukumizu-1000.hatenablog.com

▼初回の記事はコチラ

shotanukumizu-1000.hatenablog.com



HTMLテンプレートの作成


基本設定(Django側)

まずは、_project/settings.pyにアクセスして以下のコードを書いてください。

#_project/settings.py
#...(中略)...
STATIC_URL = '/static/'

STATIC_ROOT = BASE_DIR / 'staticfiles'

STATICFILES_DIRS = [str(BASE_DIR / 'static')]

定数STATIC_ROOTSTATICFILES_DIRSを新しく設定することで、Django側にcssファイルやjsファイルのようなstaticファイルを新しく読み込ませられるようになります。

次に、_project/urls.pyにアクセスして以下のコードを書いてください。

#_project/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('mdeditor/', include('mdeditor.urls')),
    path('', include('_app.urls')),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \
        + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) #追加

このように設定することで、Django側でstaticファイルを読み込ませられるようになりました。


staticファイルの読み込み

_projectフォルダと同じ場所にstaticファイルを作成してください。そして、loginform.cssを新規で作成して以下のコードを書いてください。

html,
body {
  height: 100%;
}

body {
  display: flex;
  align-items: center;
  padding-top: 40px;
  padding-bottom: 40px;
  background-color: #f5f5f5;
}

.form-signin {
  width: 100%;
  max-width: 330px;
  padding: 15px;
  margin: auto;
}
.form-signin .checkbox {
  font-weight: 400;
}
.form-signin .form-control {
  position: relative;
  box-sizing: border-box;
  height: auto;
  padding: 10px;
  font-size: 16px;
}
.form-signin .form-control:focus {
  z-index: 2;
}
.form-signin input[type="email"] {
  margin-bottom: -1px;
  border-bottom-right-radius: 0;
  border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
  margin-bottom: 10px;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

これでstaticファイルの用意は完成です。


HTMLファイルの作成

templateフォルダに移動して、それぞれ新しくsignup.htmllogin.htmlを作成してください。今回はBootstrapで多少楽をしていこうと思います。

<!----templates/signup.html---->
{% extends 'base.html' %}

{% load static %}

{% block customcss %}
<link rel="stylesheet" href="{% static 'loginform.css' %}">
{% endblock customcss %}

{% block title %}
<title>Sign Up</title>
{% endblock title %}

{% block content %}

<body class="text-center">
    {{ error }}
    <div class="container">
        <form class="form-signin" method="POST">{% csrf_token %}
            <h1 class="h3 mb-3 fw-normal">サインインする</h1>
            <label for="inputEmail" class="visually-hidden">メールアドレス</label>
            <input type="text" id="inputEmail" class="form-control" placeholder="ユーザ名" name="username" required
                autofocus>
            <label for="inputPassword" class="visually-hidden">パスワード</label>
            <input type="password" id="inputPassword" class="form-control" placeholder="パスワード" name="password" required>
            <button class="w-100 btn btn-lg btn-primary" type="submit">サインイン</button>
            <p class="mt-5 mb-3 text-muted">&copy; 2017-2021</p>
        </form>
    </div>
</body>
{% endblock content %}
<!---templates/login.html----->
{% extends 'base.html' %}

{% load static %}

{% block customcss %}
<link rel="stylesheet" href="{% static 'loginform.css' %}">
{% endblock customcss %}

{% block title %}
<title>Login</title>
{% endblock title %}

{% block content %}

<body class="text-center">
    <div class="container">
        <form class="form-signin" method="POST">{% csrf_token %}
            <h1 class="h3 mb-3 fw-normal">ログインする</h1>
            <label for="inputEmail" class="visually-hidden">メールアドレス</label>
            <input type="text" id="inputEmail" class="form-control" placeholder="ユーザ名" name="username" required
                autofocus>
            <label for="inputPassword" class="visually-hidden">パスワード</label>
            <input type="password" id="inputPassword" class="form-control" placeholder="パスワード" name="password" required>
            <button class="w-100 btn btn-lg btn-primary" type="submit">ログイン</button>
            <p class="mt-5 mb-3 text-muted">&copy; 2017-2021</p>
        </form>
    </div>
</body>
{% endblock content %}
<!---templates/index.html(ログイン完了後のページ)----->
{% extends 'base.html' %}

{% block title %}
<title>投稿内容</title>
{% endblock title %}

{% block content %}
<h1>This is an Index Page.</h1>

<a href="{% url 'logout' %}">ログアウト</a>
{% endblock content %}

あと、セキュリティ上のエラーを防ぐためDjangoで入力画面等のフォームを実装する際はform属性の最初に{% csrf_token %}を絶対つけるようにしてください。

これでログインページとアカウント登録ページは完成です。


登録(signup)

次に、Django側でログイン機能の実装をやっていきます。_app/views.pyにアクセスして、以下のコードを書いてください。

#_app/views.py
from django.db import IntegrityError
from django.shortcuts import render

from django.contrib.auth.models import User

def signupfunc(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']

        try:
            user = User.objects.create_user(username, '', password)
            return render(request, 'login.html', {})
        except IntegrityError:
            return render(request, 'signup.html', {'error': 'このユーザはすでに登録されています'})
    
  return render(request, 'signup.html', {})

これで登録(signup)のView実装は完了です。


ログイン(login)

次に、Django側でログイン(login)のViewを実装します。_app/views.pyにアクセスして、以下のコードを書いてください。

#_app/views.py
from django.db import IntegrityError
from django.shortcuts import render, redirect

from django.contrib.auth import authenticate, login

from django.contrib.auth.models import User

def signupfunc(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']

        try:
            user = User.objects.create_user(username, '', password)
            return render(request, 'login.html', {})
        except IntegrityError:
            return render(request, 'signup.html', {'error': 'このユーザはすでに登録されています'})

    return render(request, 'signup.html', {})

#追加
def loginfunc(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)

        if user is not None:
            login(request, user)
            return redirect('index')
        
        else:
            return render(request, 'login.html', {})
    
    return render(request, 'login.html', {})


ログアウト(logout)

最後に、ログアウト(logout)のViewを実装します。_app/views.pyに以下のコードを書いてください。

#_app/views.py
#_app/views.py
from django.db import IntegrityError
from django.shortcuts import render, redirect

from django.contrib.auth import authenticate, login, logout

from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required #忘れないように!


def signupfunc(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        try:
            user = User.objects.create_user(username, '', password)
            return render(request, 'login.html', {})
        except IntegrityError:
            return render(request, 'signup.html', {'error': 'このユーザはすでに登録されています'})
    return render(request, 'signup.html', {})


def loginfunc(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)

        if user is not None:
            login(request, user)
            return redirect('index')
        
        else:
            return render(request, 'login.html', {})
    
    return render(request, 'login.html', {})

#追加
@login_required
def index_func(request):
    return render(request, 'index.html', {})

def logoutfunc(request):
    logout(request)
    return redirect('login')


ルーティング設定

_app/views.pyで記述した処理をDjango側に反映させるために、_app/urls.pyに以下のコードを書いてください。

#_app/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.index_func, name='index'),
    path('signup/', views.signupfunc, name='signup'),
    path('login/', views.loginfunc, name='login'),
    path('logout/', views.logoutfunc, name='logout'),
]

これでログイン機能を完全に実装できるようになりましたので、以下のコードを書いて実際に動かしてみてください。

$ python manage.py runserver


おわりに

今回の記事ではDjangoでログイン機能を実装する方法について詳細に解説しました。

次回の記事では、Djangoのテンプレートに投稿した内容の一覧を表示させるための方法を解説していきます。