PythonMania

普段はロボットとAIを組み合わせて色々作ってます。Python関係以外も色々投稿していくと思います。

【Python】Djangoで作成したアプリに会員登録機能を追加してみる

f:id:mizuhiki0111:20190430175940p:plain


前回の続きです


前回
www.pythonmania.work


前々回
www.pythonmania.work



前回までで作成したアプリに会員登録・ログイン・ログアウト機能を追加してみます。


以下の記事を参考にさせていただきました。

it-engineer-lab.com



今回は上記の記事を参考に、以下のようなURL設計で機能を作成していきます。

URLパターン
サインアップ /accounts/signup/
ログイン /accounts/login/
ログアウト /accounts/logout/




ログイン・ログアウト機能についてはDjangoに標準の認証機能が搭載されているので、これらを使って作成していきます。

具体的にはプロジェクト内にaccountsアプリを作成し、以下のURLへrequestsを送ることで機能を実装することができます。

(今回は作りませんが、パスワード再設定なんかもできます。)

accounts/login/ [name='login']
accounts/logout/ [name='logout']
accounts/password_change/ [name='password_change']
accounts/password_change/done/ [name='password_change_done']
accounts/password_reset/ [name='password_reset']
accounts/password_reset/done/ [name='password_reset_done']
accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/reset/done/ [name='password_reset_complete']

サインアップ(新規会員登録)は提供されていないので、自分で作っていく必要があります。


順番に作成していきます。



①LOGIN_REDIRECT_URL の設定

ログイン後に表示するURLを設定していきます。


myproject/myproject/settings.pyに以下のコードを追加します。

LOGIN_REDIRECT_URL = '/'


この設定はオプションらしく、設定がない場合には/accounts/profile/ にリダイレクトされるみたいです。




②プロジェクトURLの設定

DJango標準搭載の認証機能をプロジェクトに読み込むために、プロジェクトのurls.pyに以下のコードを追加します。


path('accounts/', include('django.contrib.auth.urls')), 




③テンプレートファイルの作成
前回はindex.htmlを作成しHelloWorldしただけでしたが、今回は色々と表示していきます。



今回は上記参考サイトのhtmlファイルを参考にさせていただきました。


メインとなるbase.htmlを作成し、templates直下に保存します。

{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
    <link href="{% static 'css/style.css' %}" rel="stylesheet">
    <title>{% if request.path != '/' %}{% block title %}{% endblock %} | {% endif %}Blog App with Auth | Django2 Tutorial</title>
</head>
<body>
<div class="container">
    <header>
        <p class="site-name"><a href="{% url 'blogs:index' %}">Blog App</a></p>
        <nav>
            <ul>
                {% if user.is_authenticated %}
                <li><a href="{% url 'logout' %}" class="logout">Logout</a></li>
                {% else %}
                <li><a href="{% url 'accounts:signup' %}" class="signup">Sign up</a></li>
                <li><a href="{% url 'login' %}" class="login">Login</a></li>
                {% endif %}
                <li><a href="{% url 'blogs:create' %}" class="act">Add Post</a></li>
            </ul>
        </nav>
    </header>
    <div class="content">
        {% block content %}{% endblock %}
    </div>
</div>
</body>
</html>

次にログイン・ログアウト時のhtmlファイルを作成しますが、Django標準の認識機能で読み込めるようにtemplatesの下にregistrationフォルダを作成し、その中にhtmlファイルを作成していきます。


以下の2つを作成します


templates/registration/login.html

{% extends "base.html" %}
 
{% block content %}
 
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
 
{% if next %}
    {% if user.is_authenticated %}
    <p>Your account doesn't have access to this page. To proceed,
    please login with an account that has access.</p>
    {% else %}
    <p>Please login to see this page.</p>
    {% endif %}
{% endif %}
 
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>
 
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{% endblock %}
{% extends 'base.html' %}

{% block title %}Logout{% endblock %}

{% block content %}
<h1>Logged Out</h1>
<p>Thanks for spending some quality time with the Web site today.</p>
<p><a href="{% url 'login' %}">Log in again</a></p>
{% endblock %}

以上でログイン・ログアウト機能の実装はできました。





④サインアップ機能の実装

サインアップ機能はDjangoに搭載されていないので、自分で作っていきます。



まず以下のコマンドでサインアップ用のアプリケーションを作成します。


python manage.py startapp accounts


次に作成したアプリをいつも通りプロジェクトに認識させます


settings.pyのINSTALLED_APPSを以下のように変更します。

INSTALLED_APPS = [
    'accounts.apps.AccountsConfig', # [追加]
    'mysite.apps.MysiteConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]


またこちらもいつも通りプロジェクトのurls.pyからaccountsのurls.pyを呼び出すよう記載します。

※accountsのurls.pyはこの後作成します。


以下の一文を追加しておきます。

path('accounts/', include('accounts.urls')), 






プロジェクトのurls.pyからaccountsのurls.pyを呼び出す記載をしたので、次に作成したaccountsアプリにurls.pyを作成し、サインアップ用のURLを定義しておきます。

 
from django.urls import path
 
from . import views

app_name = 'accounts'
 
urlpatterns = [
    path('signup/', views.SignUpView.as_view(), name='signup'),
]

これでaccountsのurls.pyからviews.pyを呼び出すことができるようになりました。






最後にaccountsのview.pyを作成していきます。


サインアップ機能はログイン・ログアウト機能のように標準で搭載されているわけではありませんが、Djangoに搭載されている「UserCreationForm」というクラスを使用することで作成することが可能です。


以下のようにaccounts/views.pyを作成します。



from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views import generic


class SignUpView(generic.CreateView):
    form_class = UserCreationForm
    success_url = reverse_lazy('login')
    template_name = 'accounts/signup.html'



これでプロジェクトのurls.py→accountsアプリのviews.pyまでの流れを作成することができました。


あとはサインアップ画面のテンプレートファイルを作成すれば完了です。



templates/accountsフォルダを作成し、以下のsignup.htmlを作成しておきます。


# myblog/accounts/templates/accounts/signup.html
 
{% extends 'base.html' %}
 
{% block content %}
<h1>Sign up</h1>
<section class="common-form">
    <form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="submit">Sign up</button>
    </form>
</section>
{% endblock %}

これで

サインアップ /accounts/signup/
ログイン /accounts/login/
ログアウト /accounts/logout/

の機能を実装することができました。




ログイン状態でしか見ることができないコンテンツを作成する場合、

view.pyを以下のように変更していきます。

関数の場合
「@login_required」を関数定義の直前に記載


クラスの場合
以下のように「LoginRequiredMixin」クラスを継承

from django.contrib.auth.mixins import LoginRequiredMixin
 
class MyView(LoginRequiredMixin, View):


すればOKです!