投稿日:2019年11月14日
Djangoは簡単にWebアプリケーションを作成できるフレームワークです。この記事は初心者の方向けのDjangoチュートリアルです。
この記事ではDjangoTemplate言語でtenplateを作成します。これが終わればいよいよ見た目の確認が始められます(長かった...)!
※この記事ではblogアプリケーションのArticleテーブルにレコードがいくつか存在する前提で進んでいきます。レコードが存在しない場合は管理サイトで適当なレコードをいくつか作成して、それを公開状態にしてから進めましょう。
まずは必要なディレクトリとファイルを作成します。
sample_blog/blog/templates/
└── blog
│ ├── article_detail.html
│ └── article_list.html
└── base.html
テンプレートを書き始める前に、まずはちゃんと描画できるか確認してみましょう。
これはdetail.htmlです。
これはlist.htmlです。
開発用サーバーを起動して、ブラウザで動作を確認してみましょう。
/sample_blog $ python manage.py runserver
まずarticle_list()関数の方を確認してみましょう。http://localhost:8000/blog/をブラウザで確認してみましょう。
ちゃんと描画できていますね。次にarticle_detail()関数の方を確認してみましょう。こちらはurlで存在するArticleレコードのidを受け取る必要がありました。
とりあえず適当なidを渡してみます。
そのレコードは存在しないとエラーがかえってきました。これまでのチュートリアルでデータの削除なんかもしたので、id=1のレコードはそこで削除されていたのでしょう。
他のidのレコードを試してみます。
OK!ちゃんと表示できました!
Ctrl+Cでサーバーを停止しましょう。
もし、表示するべきArticleレコードのidがわからない場合は下の方法で確認してみましょう。
$ python manage.py shell
Python 3.6.8 (default, Oct 7 2019, 12:59:55)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from blog.models import Article
>>> Article.objects.all()[0].id
先程blogのtemplatesディレクトリの中にbase.html、更にその中のarticleレコードの中にlist.htmlとdetail.htmlを作成しました。Djangoのテンプレート言語ではプログラミング言語の様に他のテンプレートをincludeすることができます。これによって重複する処理をまとめることができます。
これから作成するtemplateはDjango独自のテンプレート言語を使って記述します。
初めての方は『HTMLの中でpythonを記述するための言語』と考えておくと良いでしょう。ここでその全ての使い方を解説することはできないので、今回使う機能だけ説明します。
DjangoTemplateLanguageについて詳しく知りたい場合は公式ドキュメントを参照してください。
実際にtemplateを記述しましょう。(今HTMLがわからない方も今はとりあえずわからないままでいいので書いてみましょう!)
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<header>
Sampleブログ
</header>
<main>
<div class="content">
{% block content %}
{% endblock %}
</div>
</main>
</body>
</html>
簡単にDjangoのTemplate Tagだけ解説します。ここで使われているTemplate Tagは2つ。{% block title %}{% endblock %}と{% block content %}{% endblock %}です。これはblockの定義しています。{% block ブロック名 %}{% endblock %}の様に定義しておくと他のテンプレートからこのhtmlファイルを継承して、そちら側からこのblockにコンテンツを埋めることができるのです。今回ここではtitleとcontentという名前でblockを定義しています。
呼び出す側の使い方は次のlist.htmlで説明します。
{% extends "base.html" %}
{% block title %}ブログ一覧|Sampleブログ{% endblock %}
{% block content %}
<h1>ブログ一覧</h1>
{% for article in articles %}
<h2>
<a href="{% url 'blog:article_detail' id=article.id %}">
{{ article.title }}
</a>
</h2>
<p class="date">
公開日:{{ article.publish }}
</p>
<p>by {{ article.author }}</p>
{{ article.body|truncatechars:30 }}
{% endfor %}
{% endblock %}
この様に他のDjangoTemplateを継承する場合は先頭に{% extends "ファイルのパス" %}と記述し、埋めるコンテンツは{% block ブロック名 %}と{% endblock %}の間に記述します。
{% extends "テンプレートのパス"%}
{% block ブロック名 %}
テンプレートのブロックに入れたいHTML
{% endblock %}
{% block ブロック名 %}
テンプレートのブロックに入れたいHTML
{% endblock %}
︙
また、新たにタグとしてfor文を使っています。article_list()からこのtemplateにはarticlesというArticleオブジェクトの配列が渡されています。Django Templateは
{% for variable in 配列 %}
繰り返し書き出すhtml
{% endfor %}
で配列をループでレンダリングできます。
次にそのループの中の"{% url 'blog:article_detail' id=article.id %}"に注目してください。これは記事詳細のページのリンクを書き出すためのタグです。前回のURLconfの中でROOTのURLconfの中のinclude()でnamespace=blog、article_detail()にマッピングするpath()でname=article_detailという値を渡していました。
URLconfをこのように定義しておくとDjangoTemplate内でこの名前でURLを呼び出すことができます。呼び出す場合は
{% url "namespace:name" オプションの引数の値 %}
とします。
{{ article.title }}や{{ article.publish }}、{{ article.author }}はループ処理しているArticleオブジェクトの変数値を書き出しています。
{{ article.body|truncatewords:30 }}に注目してみてください。このように変数値の呼び出しはパーティカルバー(|)でレンダリングにオプションを加えることができます。今回のtruncatewordsはその名の通り、呼び出しを指定した文字数までで区切ることができます。(ちなみにこれは僕のブログ記事一覧でも使っている機能です。)
ここで一端開発用サーバーを起動して確認してみましょう。
$ python manage.py runserver
http://localhost:8000/blogを開いてみましょう。
記事の一覧表示ができている!!
まだ記事の名前をクリックしても記事詳細のテンプレートdetail.htmlには何も書いていないので記事の情報は見えないですね。
では次にdetail.htmlを作成しましょう。
{% extends "base.html" %}
{% block title %}{{ article.title }}{% endblock %}
{% block content %}
<h1>{{ article.title }}</h1>
<p class="date">
公開日:{{ article.publish }}
</p>
<p>
by {{ article.author }}
</p>
{{ article.body }}
{% endblock %}
基本的に使用しているタグはlist.htmlと変わらないので説明は不要ですね?
もう一度http://localhost:8000/blogを開いてみましょう。今度は記事のリンクを押すと記事の詳細を表示してくれるのではないでしょうか?
view関数でtemplateのファイルを指定する時、"blog/article/list.html"や"blog/article/detail.html"の様に指定しました。しかし、これらのファイルを実際のパスはsample_blog/blog/templates/blog/article/list.htmlやsample_blog/blog/templates/blog/article/detail.htmlです。
どういうことでしょうか?
Djangoのtemplateファイルの扱いの設定はsettingファイルのTEMPLATESで定義します。
すこしだけみてみましょう。
[...]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
[...]
ここでDIRSとAPP_DIRSの設定がDjangoがtemplateファイルを探しに行くときの設定になります。
デフォルトの状態ではAPP_DIRSがTrueになっていて、ここを起点にtemplateファイルは検索されます。その場合、DjangoはINSTALLED_APPSに指定されたすべてのアプリケーションディレクトリ内のtempaltes/のディレクトリを探しにいきます。
つまりテンプレートのパスとして"blog/article_detail.html"
を指定した場合、全てのアプリケーションディレクトリのtemplates/blog/article_detail.html
を探しに行くことになります。
とりあえずこの章でシンプルな(ものすごくシンプルな)ブログアプリケーションができあがりました。
以下はDjangoのtemplateに関する追加Tipsです。興味があれば覗いてみてください。
「では次にdetail.htmlを作成しましょう。」の次にあるソースコード欄の名前が article_list.html になっています。たぶん、article_detail.htmlのことだと思います。