Djangoのテンプレート継承を試してみる〜extends その2:異なるフォルダ内で継承〜

  • URLをコピーしました!
目次

Django

前回、Djangoのテンプレート継承を試して、同じフォルダ内のHTMLファイルの継承を解説しました。

前回、/webapp/bmiapp/templates 内にある「index.html」を他のアプリでも共通の「base.html」とBMI計算アプリ特有のコンテンツ部分「index.html」に分離しました。

ただこのままでは共通のテンプレートである「base.html」が、アプリ内でのテンプレート継承だけになってしまっています。

今回は継承するテンプレートを他のフォルダに配置してみます。

まずは現在のフォルダ構成です(「…」は省略です)。

webapp
├── bmiapp
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── static
│   │   └── ...
│   ├── templates
│   │   └── bmiapp
│   │       ├── base.html
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── db.sqlite3
├── index
│   └── ...
├── index.cgi
├── linearfunction
│   └── ...
├── manage.py
├── quadraticfunction
│   └── ...
├── static
│   └── ...
└── webapp
    ├── __init__.py
    ├── asgi.py
    ├── definitions.py
    ├── params.json
    ├── settings.py
    ├── urls.py
    └── wsgi.py

それでは始めていきましょう。

共有テンプレート用アプリの作成

まずはどのアプリからでも共有テンプレートにアクセスできるように、共有テンプレート用のアプリを作成しましょう。

新規のアプリの登録に関してはこちらでも解説していますので、よかったらどうぞ。

ターミナルからwebappまで移動し、いつものアプリ作成のコマンドを実行します。

今回、共有テンプレート用アプリの名称を「basetemplates」としました。

django-admin startapp basetemplates

そして/webapp/urls.py とsettings.pyを修正します。

urls.pyではurlpatternsに「path(‘basetemplates/’,include(‘basetemplates.urls’)),」します。

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('index.urls')),
    path('basetemplates/',include('basetemplates.urls')),
    path('bmiapp/', include('bmiapp.urls')),
    path('linearfunction/', include('linearfunction.urls')),
    path('quadraticfunction/', include('quadraticfunction.urls')),
]

settings.pyではINSTALLED_APPSに「basetemplates」を追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'basetemplates',
    'index',
    'bmiapp',
    'linearfunction',
    'quadraticfunction',
]

そして新たに作成された/webapp/basetemplates のviews.pyを修正し、urls.pyを新規作成します。

views.py はこのような単純な構成で大丈夫です。(もしかしたらもっと簡単にできるかも?)

from django.shortcuts import render
from django.http import HttpResponse
import sys
sys.path.append('../')
from webapp import definitions

def index(request):
    params = definitions.readjson()

    return render(request, 'basetemplates/index.html', params)

urls.pyはこんな感じです。

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index')
]

そしてテンプレートを保存するため、/webapp/basetemplates 内に「templates」フォルダを、そしてそのtemplatesフォルダ内に「basetemplates」フォルダを作成しましょう。

つまりフォルダ構成としてはこうなります。

webapp
├── basetemplates
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── templates
│   │   └── basetemplates
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── bmiapp
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── static
│   │   └── ...
│   ├── templates
│   │   └── bmiapp
│   │       ├── base.html
│   │       └── index.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── db.sqlite3
├── index
│   └── ...
├── index.cgi
├── linearfunction
│   └── ...
├── manage.py
├── quadraticfunction
│   └── ...
├── static
│   └── ...
└── webapp
    └── ...

これで準備が完了しました。

他のフォルダからテンプレートを継承

それでは他のフォルダからテンプレートを敬称してみましょう。

新たに作成した/webapp/basetemplates/templates/basetemplates 内に共通で使用したいHTMLファイルを保存します。

今回の場合、「base.html」です。

ちなみに内容としてはこんな感じです。

<!doctype html>
{% load static %}
<html lang="ja">
<head>
    <meta charset="utf-8">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="{% static 'style.css' %}">
    <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
    <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
    <link rel="icon" type="image/png" href="{% static 'favicon.png' %}">
    {% block title %}
    {% endblock %}
</head>
<body class="container">
    <!-- title -->
    <div class="row">
        <div class="col" style="text-align: left; margin:2rem 0rem 0rem 0rem;">
            <a href={{index_url}}><img class="image_logo_m" src="{% static '3pysci_logo.png' %}"></a>
        </div>
    </div>
    <!-- /title -->
    <!-- main&link-->
    <div class="row">
        <!-- main -->
        <div class="col-12 col-lg-10" style="margin:2rem 0rem 0rem 0rem;">
        {% block content %}
        {% endblock %}
        </div>
        <!-- /main -->
        <!-- link -->
        <div class="col-12 col-lg-2" style="margin:2rem 0rem 0rem 0rem;">
            {% for cat, urls in link.items %}
                <p style="font-weight: bold; ">・{{cat}}</p>
                {% for name, url in urls.items %}
                <p style="text-indent: 1rem;"><a href={{index_url}}{{url}}>{{name}}</a></p>
                {% endfor %}
            {% endfor %}
        </div>
        <!-- /link -->
    </div>
    <!-- /main&link -->
    <!-- copyright -->
    <div class="row">
        <div class="col" style="text-align: center; margin:2rem 0rem 0rem 0rem;">
            {{copyright}}
        </div>
    </div>
    <!-- /copyright -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
</body>
</html>

次にコンテンツ部分である/webapp/bmiapp/templates/bmiapp/index.htmlを修正します。

修正部分は「{% extends “bmiapp/base.html” %}」でこの継承先を「basetemplates/base.html」に変更し、「{% extends “basetemplates/base.html” %}」とします。

{% extends "basetemplates/base.html" %}

{% block title %}
<title>{{ title }}|ライフ:BMI</title>
{% endblock %}

{% block content %}
<h1>ライフ:BMI(Body Mass Index)</h1>
<p>BMI(Body Mass Index)は体重と身長から計算される肥満度を表す指数。</p>
<p>計算式は <font size="6">\(BMI=\frac{w}{h^2}\)</font>     w:体重(kg) h:身長(m)</p>
<p><font size="4"> </font></p>
<table class="mx-auto">
    <form action="/bmiapp/" method="post">
        {% csrf_token %}
        <tr>
        <td style="text-align: right;">{{ forms.height.label }}</td><td>{{ forms.height }}</td><td>cm</td>
        </tr>
        <tr>
        <td style="text-align: right;">{{ forms.weight.label }}</td><td>{{ forms.weight }}</td><td>kg</td>
        </tr>
        <tr>
        <td></td><td style="text-align: right;"><input type='submit' value="click"></td><td></td>
        </tr>
    </form>
    <tr><td><br></td><td></td><td></td></tr>
    <tr><td style="text-align: right;">BMI値:</td><td style="text-align: center;">{{ bmi }}</td><td></td></tr>
    <tr><td style="text-align: right;">適正体重:</td><td style="text-align: center;">{{ optimal }}</td><td>kg</td></tr>
</table>
<p style="text-align: center;"><font size="6">{{ result }}</font></p>
<table class="table table-striped mx-auto" style="width:auto">
    <tr><td colspan="3"><font size="4"><b>日本肥満学会の基準</b></font></td></tr>
    <tr><td>状態</td><td colspan="2">BMIの指標</td></tr>
    <tr><td>低体重(痩せ)</td><td>18.50未満</td><td>低体重</td></tr>
    <tr><td>普通体重</td><td>18.50以上25.00未満</td><td>標準</td></tr>
    <tr><td>肥満(1度)</td><td>25.00以上30.00未満</td><td rowspan="2">肥満</td></tr>
    <tr><td>肥満(2度)</td><td>30.00以上35.00未満</td></tr>
    <tr><td>肥満(3度)</td><td>35.00以上40.00未満</td><td rowspan="2">高度肥満</td></tr>
    <tr><td>肥満(4度)</td><td>40.00以上</td></tr>
</table>
{% endblock %}

これでテンプレートの継承はこのようになりました。

実際に表示させてみたのがこちらですが、これまでと変わらない形で表示することができています。

ここまでできれば他のアプリに関しても同様にタイトル部分とコンテンツ部分だけ抜き出し、こちらの「index.html」にはめ込んでやればテンプレートの継承ができるようになります。

{% extends "basetemplates/base.html" %}

{% block title %}
<title>#タイトルを記載</title>
{% endblock %}

{% block content %}
#コンテンツを記載
{% endblock %}

このようにテンプレート化することで、修正ファイルが減らせるだけでなく、見た目的にもすっきりとしたHTMLにできるので、コンテンツを作成することがだいぶ楽になりそうです。

次回は違うタイプのテンプレート継承「include」を試してみることにします。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次
閉じる