その2:ビューと認証
技術スタック DjangoPythonLaravelPHP

その2:ビューと認証

2022.02.13

こんにちはjunです。この記事はLaravel開発者がDjangoでアプリ作成の学習について解説しています。Laravelでいうこの機能はDjangoのここである、その逆はこうだと「Laravelとリンクさせて学習する」ことを重視しています。

前回は環境構築やアプリの概要、設定ファイルとディレクトリ構成の解説を行いました。今回の記事は

  • テンプレートを使用したViewの作成
  • 静的ファイルの使用方法
  • 認証機能の実装

以上を行いたいと思います。

View(テンプレート)の作成

ではウェルカムページをカスタムのViewを表示することをやってみましょう。ちなみに、DjangoではMVTというコンセプトで作成され、LaravelのMVCとは少し意味合いが異なるそうです。見た目の部分はMVCではV(View)と定義しますが、MVTではT(Template)でありV(View)はリクエストを受け取り、レスポンスを定義します。

そのため今後はMVTに則り、見た目の部分の機能に関してはTemplateと呼ぶこととします。

テンプレートの仕組み

テンプレートとは見た目(htmlレスポンス)を定義するファイルのことで.htmlで定義します。Laravelではresources/views/配下に~~.blade.phpというブレードを用いて見た目のhtmlを定義するのと同じです。

ソースのルートディレクトリにtemplates/ディレクトリ を作成し、base.htmlをさらに作成します。

├── db.sqlite3
├── djangodemo
├── manage.py
└── templates
    └── base.html

このソースルートのtemplatesはすべてのアプリで使用することができます。

テンプレートの書き方

base.htmlを作成します。まず以下の様に作成してみます。

base.html
<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">
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
        <link rel="stylesheet" href="{% static 'style.css' %}">
        <title>test</title>
    </head>
    <body>
        <header>
            <nav class="navbar navbar-light bg-info">
                <div class="container">
                    <a class="navbar-brand" href="/">Navbar</a>
                </div>
            </nav>
        </header>
        <main class="d-block bg-light">
            <div class="container p-4 bg-white l-main-area">
                test
            </div>
        </main>
        <footer></footer>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
    </body>
</html>

bootstrapを入れておきます。変数などは定義していませんが、ひとまずウェルカムページを上記の内容に書き換えましょう。

テンプレートをレスポンスで返してみる

テンプレート作成したらdjangodemo/urls.pyを以下の様に変更します。

urls.py
from django.contrib import admin
from django.urls import path
from django.views.generic import TemplateView # わすれずに

urlpatterns = [
    path('',TemplateView.as_view(template_name='base.html')), # これを追加
    path('admin/', admin.site.urls),
]

urls.pyはLaravelでいうroutes/配下のファイルであり、URLに対応する処理やテンプレートを指定する箇所です。上記の記述を用いて、http://localhost:8000/にアクセスした時に先ほどの、base.htmlを表示する様にしています。テンプレートを直接指定してレスポンスとして返すにはTemplateViewが必要です。

Laravel的には以下の様な記述です。

routes/web.php
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('base');
});

urls.pyを編集したらhttp://localhost:8000/にアクセスして以下の様な画面が表示されればひとまず、特定のURLにテンプレートを返すという感覚がわかると思います。

ひとまずカスタムテンプレートを表示できたのでDjangoで使用できる様々なディレクティブを解説します。

ディレクティブというのはそのプログラム(ここではDjango)が解釈できる文字列の記述のことです。Djandgoでは {% if %} のような記号を用いて表現します。Laravelのブレードでは @if などです。

テンプレートで使えるディレクィブ

変数展開

Viewからはテンプレートにはデータを渡すことができます。渡す時はDictで渡します。

views.py
from django.shortcuts import render
def index(request):
    context = {'value': 123}
    return render(request, 'polls/index.html', context)

そして変数を展開する時は{{ }} を用いて展開をします。値は自動的にエスケープ処理されます。ここはLaravelと同じですね。

template.html
<p>{{ value }}</p>

template.html
<p>123</p>

for文

for分は以下の様に使用します。

<!-- list = [{'name':'jun'},{'name':'apps'},{'name':'python'}] -->
<ul>
{% for item in list %}
<li>{{ item.name }}</li>
{% endfor %}
</ul>

<ul>
<li>{{ item.jun }}</li>
<li>{{ item.apps }}</li>
<li>{{ item.python }}</li>
</ul>

Laravelでは @forディレクティブでしたね。ですが基本的に似ています。

if文

if文は以下の様に使用します。

{% if user.is_authenticated%}
<li class="nav-item">
    <a class="nav-link" href="{% url 'logout' %}">ログアウト</a>
</li>
{% else %}
<li class="nav-item">
    <a class="nav-link active" aria-current="page" href="{% url 'login' %}">ログイン</a>
</li>
{% endif %}

Laravelでは @ifディレクティブでした。基本的に似ています。上記の例はユーザーのログイン状態で表示を分岐しています。

フィルタ

Laravelは{{ count($value) }} のように変数展開しつつもメソッドを使用することができます。しかし、Djangoの場合は内部にロジックを書くことができません。その代わりフィルタというものを使用して変数の値を変更します。

<!-- usersはリスト -->
<p>登録者数は{{ users|length }}人です。</p>

{{ 変数名|フィルタ名:<引数など>}}この様な入力規則になっています。

<p>作成日:{{ created_at|date:"Y年m月d日 H:s:i" }}</p>

上記の例はcreated_atを所定の日付フォーマットに変えるフィルタです。

使用可能なフィルタはこちらのドキュメントに記載されています。

URL

Laravelでは route() というヘルパーを使用することでroutes/web.php などで定義した名前付きルートのURLを出力できます。Djangoにも似た様なものがあり、以下の様に表現します。

{% url "index" %}

またキーワード引数がある場合、例えばブログ記事の詳細を/blogs/1 のように示す場合route('blogs',['blog_id'=>1])のように引数を指定できます。Djangoも同様に

{% url "blogs" blog_id=1 %}

のように表示します。

エスケープ解除

リッチテキストを表示したい時などLaravelでは{!! !!}とすることでエスケープを解除していました。Djangoの場合は2通りあります。

1つはsafeフィルタを使う方法と、2つ目はエスケープ解除ディレクティブで囲むことです。

<div class="editor">
{{ value|safe }}
</div>

{% autoescape off %}
<div class="editor">
    {{ value }}
</div>
{% endautoescape %}

エスケープを解除するとXSS脆弱性の元になります。展開する変数のチェックを怠らない様にしましょう。

テンプレートの共通化と継承

Laravelのテンプレートには @extends@sectionをなどを用いて共通化を行うことができます。Djangoでも同じ様な方法で共通化が行えます。例えばbase.html に共通のヘッダやメニューなどを書いておき、任意のテンプレートに継承させてコンテンツだけ出力させることができます。

templates/base.html
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>{% block title %}{% endblock  %}</title>
    </head>
    <body>
        <header>
            <!-- 省略 -->
        </header>
        <main>
            {% block content %}{% endblock  %}
        </main>
        <footer>
            <!-- 省略 -->
        </footer>
    </body>
</html>

base.htmlでは共通のヘッダーなどを定義しておきます。そして{% block content %}{% endblock %}で子テンプレートで入力できる値を定義します。ここではタイトル(title)と内容(content)を入力できる様にします。

templates/detail.html
{% extends 'base.html' %}

{% block title %}詳細ページ{% endblock  %}

{% block content %}
<p> content </p>
{% endblock  %}

小テンプレート では上記の様に書くことで、親のbase.html に当てはめられた形でレンダリングされます。

静的ファイルの呼び出し

プロジェクトで配置しておくcss,js,画像といった静的ファイルをLaraveで扱うときはpublic/ ディレクトリ配下にcss/,js/,images/などを配置して {{assets('/css/style.css')}} とすることで自動的にパスの解決をしてくれます。

Djangoで静的ファイルを利用するためには2つほど設定が必要です。

setting.pyでの設定

まずsetting.py にて静的ファイルを配置するディレクトリの設定を確認します。

認証機能実装

Djangoの基本機能を使用する

ユーザー登録

ログイン

パスワード忘れ

メールアドレスに変更する

コメント

コメント読み込み中..

Copyright © 2021 jun. All rights reserved.