Share via


手順 3: Django アプリで静的ファイルを提供し、ページを追加し、テンプレートの継承を使用する

前の手順: ビューおよびページ テンプレートを使用して Django アプリを作成する

このチュートリアルの前の手順では、単一の HTML ページを使って最小限の Django アプリを作成する方法を学びました。 ただし、最新の Web アプリには多くのページが含まれています。 最新の Web ページでは、スタイルおよび動作に一貫性を持たせるために、CSS や JavaScript ファイルなどの共有リソースが使用されています。

この手順では、次の方法を学習します。

  • 便利なスケルトン コードによってさまざまな種類の新しいファイルを迅速に追加するための Visual Studio の項目テンプレートを使用する (手順 3-1)
  • 静的ファイルを提供するように Django プロジェクトを構成する (手順 3-2)
  • アプリに追加ページを付け加える (手順 3-3)
  • テンプレートの継承を使用して、複数のページで使用されるヘッダーとナビゲーション バーを作成する (手順 3-4)

手順 3-1:項目テンプレートを理解する

Django アプリを開発する場合、通常は多くの Python、HTML、CSS、および JavaScript ファイルを追加します。 Visual Studio では、ファイルの種類 (デプロイに必要になる可能性がある web.config のような他のファイル) ごとに、すぐに使用できる便利な項目テンプレートを提供しています。

使用可能なテンプレートを確認するには、ソリューション エクスプローラーに移動して、項目を作成するフォルダーを右クリックし、[追加]>[新しい項目] の順に選択します。

Add new item dialog in Visual Studio.

テンプレートを使用するには、目的のテンプレートを選択して、ファイルの名前を指定し、[追加] をクリックします。 この方法で項目を追加すると、Visual Studio プロジェクトに自動的にファイルを追加して、ソース管理への変更にマーク付けされます。

質問:Visual Studio では、提供する項目テンプレートをどのように把握していますか。

回答:Visual Studio プロジェクト ファイル ( .pyproj) には、Python プロジェクトとしてマーク付けするプロジェクト タイプ識別子が含まれます。 Visual Studio では、このタイプ識別子を使用して、プロジェクト タイプに適合する項目テンプレートのみを表示します。 このように、Visual Studio では、多数のプロジェクト タイプに対応する豊富な項目テンプレート セットを提供でき、項目テンプレートを毎回分類して調べる必要はありません。

手順 3-2:アプリからの静的ファイルを提供する

Python でビルドされた Web アプリ (任意のフレームワークを使用) では、Python ファイルは常に Web ホストのサーバー上で実行されます。 Python ファイルもユーザーのコンピューターに転送されることはありません。 ただし、CSS や JavaScript などのその他のファイルは、ブラウザーで排他的に使用されます。 そのため、それらは要求されるたびに、ホスト サーバーからそのまま配信されます。 このようなファイルは "静的" ファイルと呼ばれ、Django では、コードを記述しなくても自動的にこれらのファイルを配信できます。

Django プロジェクトの settings.py にある以下の行のおかげで、Django プロジェクトは、既定では、アプリの static フォルダーから静的ファイルを提供するように設定されています。

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = posixpath.join(*(BASE_DIR.split(os.path.sep) + ['static']))

任意のフォルダー構造を使用して目的の static 内にファイルを編成してから、そのフォルダー内で相対パスを使用してファイルを参照することができます。 このプロセスを試行するには、次の手順に従って CSS ファイルをアプリに追加してから、index.html テンプレートに該当するスタイルシートを使用します。

  1. ソリューション エクスプローラーで、Visual Studio プロジェクトの HelloDjangoApp フォルダーを右クリックして、[追加]>[新しいフォルダー] を選択して、フォルダーに static という名前を付けます。

  2. static フォルダーを右クリックし、[追加]>[新しい項目] を選択します。 表示されたダイアログ ボックスで、Stylesheet テンプレートを選択して、ファイルに site.css という名前を付けて、[追加] をクリックします。

    Add new item dialog for static file.

    site.css ファイルがプロジェクトに表示され、エディターで開かれます。 次の画像のようなフォルダー構成が表示されます。

    Static file structure as shown in Solution Explorer.

  3. site.css の内容を次のコードに置き換えて、ファイルを保存します。

    .message {
        font-weight: 600;
        color: blue;
    }
    
  4. アプリの templates/HelloDjangoApp/index.html ファイルの内容を次のコードに置き換えます。 このコードでは、手順 2 で使用した <strong> 要素を、message スタイル クラスを参照する <span> に置き換えています。 スタイル クラスを使用すると、要素のスタイル設定をこれまで以上に柔軟に行えます。 (VS 2017 15.7 以前の使用時、index.html ファイルを templates 内のサブフォルダーに移動済みの場合、手順 2-4 のテンプレートの名前空間の設定に関する記述を参照してください)。

    <html>
        <head>
            <title>{{ title }}</title>
            {% load static %} <!-- Instruct Django to load static files -->
            <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
        </head>
        <body>
            <span class="message">{{ message }}</span>{{ content }}
        </body>
    </html>
    
  5. プロジェクトを実行して、結果を確認します。 完了したら、サーバーを停止し、(手順 2 の説明にあるように) 必要に応じてソース管理に対する変更をコミットします。

質問: {% load static %} タグの目的は何ですか。

回答: <head><body> のような要素で静的ファイルを参照する前に、{% load static %} 行が必要です。 このセクションで示した例では、"静的ファイル" ではカスタム Django テンプレート タグ設定を参照しています。これにより、{% static %} 構文を使って静的ファイルを参照できます。 {% load static %} がないと、アプリが実行されたときに例外が表示されます。

質問:静的ファイルを編成するにあたって、何らかの規則はありますか。

回答: static フォルダーには、他の CSS、JavaScript、HTML ファイルを自由に追加できます。 静的ファイルを編成する一般的な方法は、fontsscriptscontent (スタイルシートとその他のファイル用) という名前のサブフォルダーを作成することです。 どの場合も、{% static %} 参照の相対ファイル パスにこれらのフォルダーを必ず含めてください。

質問: {% load static %} タグを使用せずに同じタスクを完了することはできますか。

回答: はい、できます。

<html>
    <head>
        <title>{{ title }}</title>
        <link rel="stylesheet" type="text/css" href="../../static/site.css" />
    </head>
    <body>
        <span class="message">{{ message }}</span>{{ content }}
    </body>
</html>

手順 3-3:アプリにページを追加する

アプリに別のページを追加すると、次のようになります。

  • ビューを定義する Python 関数を追加する。
  • ページのマークアップのためにテンプレートを追加する。
  • Django プロジェクトの urls.py ファイルに必要なルーティングを追加する。

次の手順では、"HelloDjangoApp" プロジェクトに "About" ページと、ホーム ページからこのページへのリンクを追加します。

  1. ソリューション エクスプローラーで、templates/HelloDjangoApp フォルダーを右クリックします。 [追加]>[新しい項目] の順に選択し、[HTML ページ] 項目テンプレートを選択します。 ファイルに about.html という名前を付けて、 [追加] を選択します。

    Add new item dialog for about file.

    ヒント

    [新しい項目] コマンドが [追加] メニューに表示されない場合、Visual Studio がデバッグ モードを終了できるようにサーバーを確実に停止済みにしてください。

  2. about.html の内容を次のマークアップに置き換えます (手順 3-4 で、ホーム ページへの明示的なリンクをシンプルなナビゲーション バーに置き換えます)。

    <html>
        <head>
            <title>{{ title }}</title>
            {% load static %}
            <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
        </head>
        <body>
            <div><a href="home">Home</a></div>
            {{ content }}
        </body>
    </html>
    
  3. アプリの views.py ファイルを開き、次のテンプレートを使用する about という名前の関数を追加します。

    def about(request):
        return render(
            request,
            "HelloDjangoApp/about.html",
            {
                'title' : "About HelloDjangoApp",
                'content' : "Example app page for Django."
            }
        )
    
  4. Django プロジェクトの urls.py ファイルを開き、次の行を urlPatterns 配列に追加します。

    re_path(r'^about$', HelloDjangoApp.views.about, name='about'),
    
  5. templates/HelloDjangoApp/index.html ファイルを開き、<body> 要素の下に次の行を追加して、About ページにリンクします (このリンクは手順 3-4 でナビゲーション バーに、再度、置き換えることになります)。

    <div><a href="about">About</a></div>
    
  6. [ファイル]>[すべて保存] メニュー コマンドを使用するか、または単純に Ctrl+Shift+S キーを押して、すべてのファイルを保存します (技術的には、Visual Studio でプロジェクトを実行するとファイルが自動的に保存されるので、この手順は必要ありませんが、知っておくとよいコマンドです)。

  7. プロジェクトを実行して結果を確認し、ページ間の移動をチェックします。 完了したら、サーバーを閉じます。

回答: views.py ファイルのビュー関数が index という名前であっても、Django プロジェクトの urls.py ファイルにある URL ルーティング パターンは、文字列 "index" と一致する正規表現を含みません。 この文字列と一致させるには、パターン ^index$ に対応する別のエントリを追加する必要があります。

次のセクションで示すように、ページ テンプレートの {% url '<pattern_name>' %} タグを使用して、パターンの "名前" を参照することをお勧めします。 その場合は、Django によって自動的に適切な URL が作成されます。 たとえば、about.html<div><a href="home">Home</a></div><div><a href="{% url 'index' %}">Home</a></div> に置き換えます。 urls.py にある最初の URL パターンは実際、(name='index' 引数の特性により) 'index' という名前になるため、ここでは 'index' の使用が有効です。 また、2 番目のパターンを参照するには、'home' を使用することもできます。

手順 3-4:テンプレートの継承を使ってヘッダーとナビゲーション バーを作成する

最新の Web アプリでは、各ページに明示的なナビゲーション リンクを使用するのでなく、ブランド化ヘッダーとナビゲーション バーが使用されます。 ナビゲーション バーには、最も重要なページ リンクやポップアップ メニューなどが用意されています。 ヘッダーとナビゲーション バーがすべてのページで確実に同じになるようにするには、各ページ テンプレートで同じコードを繰り返さないことです。 代わりに、すべてのページの共通部分を 1 つの場所に定義します。

Django のテンプレート システムでは、複数のテンプレート間で特定の要素を再利用するために、インクルードと継承という 2 つの方法を提供しています。

  • インクルードとは、構文 {% include <template_path> %} を使用して参照元テンプレートの特定の場所に挿入する他のページ テンプレートのことです。 コード内で動的にパスを変更する場合、変数を使用することもできます。 インクルードは、ページ上の特定の場所に共有テンプレートを組み入れるために、ページの本文で使用されます。

  • 継承は、ページ テンプレートの冒頭で {% extends <template_path> %} を使用して、参照元テンプレートが構築される共有の基本テンプレートを指定します。 継承は一般的に、アプリのページの共有レイアウト、ナビゲーション バー、およびその他の構造を定義するために使用されます。これにより、参照元テンプレートで実行できるのは、ブロックと呼ばれる基本テンプレートの特定の領域を追加または修正することだけです。

どちらの場合も、<template_path> はアプリの templates フォルダーへの相対です (../ または ./ も許可されます)。

基本テンプレートでは、{% block <block_name> %}{% endblock %} タグを使用してブロックを表現します。 参照元テンプレートで同じブロック名のタグを使用している場合、基本テンプレートの内容は、そのブロックの内容でオーバーライドされます。

次の手順では、継承を例示します。

  1. アプリの templates/HelloDjangoApp フォルダーで、新しい HTML ファイルを作成します。 templates/HelloDjangoApp フォルダーを右クリックし、[追加]>[新しい項目] の順に選択してから、[HTML ページ項目] テンプレートを選択します。 ファイルに layout.html という名前を付けて、 [追加] を選択します。

    Add new item dialog for layout file.

  2. layout.html ファイルの内容を次のマークアップに置き換えます。 このテンプレートには、すべての参照元ページを置き換える必要がある "content" という名前のブロックが含まれていることがわかります。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>{{ title }}</title>
        {% load static %}
        <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
    </head>
    
    <body>
        <div class="navbar">
           <a href="/" class="navbar-brand">Hello Django</a>
           <a href="{% url 'home' %}" class="navbar-item">Home</a>
           <a href="{% url 'about' %}" class="navbar-item">About</a>
        </div>
    
        <div class="body-content">
    {% block content %}{% endblock %}
            <hr/>
            <footer>
                <p>&copy; 2018</p>
            </footer>
        </div>
    </body>
    </html>
    
  3. 次のスタイルをアプリの static/site.css ファイルに追加します (このチュートリアルでは、レスポンシブ設計を示すことを意図していません。以下に示したスタイルは単純に、面白い結果を生成します)。

    .navbar {
        background-color: lightslategray;
        font-size: 1em;
        font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
        color: white;
        padding: 8px 5px 8px 5px;
    }
    
    .navbar a {
        text-decoration: none;
        color: inherit;
    }
    
    .navbar-brand {
        font-size: 1.2em;
        font-weight: 600;
    }
    
    .navbar-item {
        font-variant: small-caps;
        margin-left: 30px;
    }
    
    .body-content {
        padding: 5px;
        font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    
  4. 基本テンプレートを参照して、ページ内で使用できるように、templates/HelloDjangoApp/index.html ファイルを変更します。 HTML ページの 1 行目 (html タグの上) として次の行を追加します。

    {% extends "HelloDjangoApp/layout.html" %}
    
  5. 継承を使用すると、このテンプレートは body タグ内で実装しやすくなり、コンテンツ ブロックをオーバーライドできることがわかります。

    {% block content %}
    <span class="message">{{ message }}</span>{{ content }}
    {% endblock %}
    
  6. レイアウト テンプレートを使用できるようにするのと同じ方法で、templates/HelloDjangoApp/about.html ファイルを変更します。 HTML ページの手順 1 と同じ行 (html タグの上) を追加します。

    {% extends "HelloDjangoApp/layout.html" %}
    
  7. 次に、継承を使用して、body タグ内にテンプレートを実装して、コンテンツ ブロックをオーバーライドします。

    {% block content %}
    {{ content }}
    {% endblock %}
    
  8. サーバーを実行して、結果を確認します。 完了したら、サーバーを閉じます。

    Running app showing the nav bar.

  9. アプリに十分な変更を加えたので、このタイミングで再びソース管理に変更をコミットすることが適切です。

次のステップ

詳しい説明