Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Djangoテンプレートエンジンを使いこなそう!
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Shinya Okano
October 06, 2023
Technology
3.1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Djangoテンプレートエンジンを使いこなそう!
Shinya Okano
October 06, 2023
More Decks by Shinya Okano
See All by Shinya Okano
プロファイラを使ってPythonアプリをチューニングしよう
tokibito
2
1.4k
Pythonのデバッガーを使おう
tokibito
1
960
Djangoフレームワークの紹介_OSC北海道2019
tokibito
1
1.1k
DjangoCongressJP開催レポート
tokibito
0
100
Djangoフレームワークの紹介 OSC2018do
tokibito
0
2.9k
Other Decks in Technology
See All in Technology
OTel × Datadog で 「AI活用」を計測し、改善に繋げる
shihochan
2
1.1k
飲食店もAIで。レジ締めやハンディシステムをつくってる話 / Using AI for restaurant management
vtryo
0
200
起点・思考・出力で分解する 〜PM業務の自動化設計〜
kazu_kichi_67
2
1.1k
フルAIで個人開発して学んだあれこれ / yuruai vol.1
isaoshimizu
0
150
Why is RC4 still being used?
tamaiyutaro
0
170
[チョークトーク資料]AWS DevOps Agent を使いこなす / AWS Dev Ops Agent Chalk Talk AWS Summit Japan 2026
kinunori
4
810
Docker Desktop不要の時代が来る? WSL標準の「wslc」で Linuxコンテナを動かしてみた.
ueponx
0
180
BPaaSで進むAIオペレーションの現在地 AI実装が効く領域とスケーラビリティの選定と実装
kentarofujii
0
210
Oracle Cloud Infrastructure:2026年6月度サービス・アップデート
oracle4engineer
PRO
1
380
Hatena Engineer Seminar 37 jj1uzh
jj1uzh
0
180
5分でわかる Amazon Connect_20260608
hwangbyeonghun
0
130
テスト設計の本質を改めて考えてみる~生成AIを活用する時代だからこそ、作ったテストの説明性を高めよう~
yamasaki696
1
150
Featured
See All Featured
GitHub's CSS Performance
jonrohan
1033
470k
GraphQLとの向き合い方2022年版
quramy
50
15k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.5k
Scaling GitHub
holman
464
140k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.2k
A better future with KSS
kneath
240
18k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
350
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Producing Creativity
orderedlist
PRO
348
40k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6k
Transcript
Djangoテンプレートエンジンを 使いこなそう! DjangoCongressJP 2023 @tokibito
お前誰よ? • 岡野真也 • X (twitter): @tokibito • 株式会社ObotAI 取締役CTO
• 株式会社オープンコレクター 取締役 • Djangoフレームワークは2006年ごろから使ってる
アジェンダ • Djangoテンプレートエンジン概要 • アプリからの使い方 • テンプレート言語を使いこなす • テンプレートエンジンのカスタマイズ
Djangoテンプレートエンジン 概要
Djangoテンプレートエンジン • Djangoには、組み込みのテンプレートエンジンがあります。 • django.template
Djangoテンプレートエンジンの機能 • テンプレートを使って文字列を生成する • =レンダリングする • コンテキストを渡すことで、レンダリング時に動的に内容を変 更できる • テンプレート言語により、柔軟に出力内容を制御できる
• テンプレートローダーにより、テンプレートをファイルから読 み込める
テンプレートを使って 文字列を生成する
Django shellで試す >>> from django.template import engines >>> # テンプレートエンジンインスタンスの取得
>>> django_engine = engines["django"] >>> # テンプレート文字列をコンパイルして、Templateインスタンス生成 >>> template = django_engine.from_string("Hello {{ name }}!") >>> # コンテキストを指定してテンプレートをレンダリング >>> template.render({"name": "spam"}) 'Hello spam!' https://docs.djangoproject.com/en/4.2/topics/templates/#django.template.loader.engines
テンプレートにコンテキストを渡す • テンプレートにコンテキスト(context, 文脈)を渡すと、レンダ リング時に動的に内容を変更できる • キー(key)と値(value)の組み合わせで複数渡せる • Pythonの辞書を渡せる、と考えておけばOK
テンプレートのレンダリング テンプレート コンテキスト レンダリング結果 文字列 レンダリング
コンテキストを使う例 >>> from django.template import engines >>> # テンプレートエンジンインスタンスの取得 >>>
django_engine = engines["django"] >>> # テンプレート文字列をコンパイルして、Templateインスタンス生成 >>> template = django_engine.from_string("Hello {{ name }}!") >>> # コンテキストを指定してテンプレートをレンダリング >>> template.render({"name": "spam"}) 'Hello spam!' >>> # コンテキストを変更した場合 >>> template.render({"name": "egg"}) 'Hello egg!'
アプリからの使い方
Djangoドキュメントのチュートリアル • 「はじめての Django アプリ作成、その 3」 • https://docs.djangoproject.com/ja/4.2/intro/tutorial03/ • テンプレートファイルの作成、使い方の説明がある
ひとまずやってみる • プロジェクトのデフォルト設定で、テンプレートファイルを利用可能 • startappでmyappを作り、settings.pyのINSTALLED_APPSに追加してお く
from django.shortcuts import render # Create your views here. def
my_view(request): return render(request, 'spam.html', {'name': 'egg'}) myapp/views.py Hello {{ name }} myapp/templates/spam.html from myapp import views urlpatterns = [ path('', views.my_view), path('admin/', admin.site.urls), ] myproject/urls.py
None
コンテキストを使う例 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], #
任意のテンプレートディレクトリ追加 'APP_DIRS': True, # アプリのtemplatesを使うか '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', ], }, }, ]
settings.py: BACKEND • テンプレートエンジンのバックエンド設定 • デフォルトはDjangoTemplates=Djangoテンプレートエンジン • 変更すると、Jinja2などのDjango以外のテンプレートエンジンを利 用可能 •
django.contrib.adminなど、Djangoに組み込まれている機能は、 Djangoテンプレートエンジンを前提にしている実装が多い • TEMPLATES設定はリストで複数記述できるので、Jinja2との併用 は可能 'BACKEND': 'django.template.backends.django.DjangoTemplates',
settings.py: DIRS • テンプレートファイルを配置するディレクトリ • 絶対パスで記述する必要がある。 'DIRS': [], # from
pathlib import Path # BASE_DIR = Path(__file__).resolve().parent.parent 'DIRS': [ BASE_DIR / 'templates', # プロジェクト直下のtemplatesディレクトリ ]
settings.py: APP_DIRS • アプリケーション内のtemplatesディレクトリを検索対象にす るかどうか • myapp/templates が検索対象となる。 'APP_DIRS': True,
settings.py: OPTIONS.context_processors • コンテキストプロセッサ、後ほど説明 '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', ], },
View関数でテンプレートを使う from django.shortcuts import render # Create your views here.
def my_view(request): return render(request, 'spam.html', {'name': 'egg'}) myapp/views.py render関数は、便利なショートカット関数 render(request, template_name, context=None, content_type=None, status=None, using=None) https://docs.djangoproject.com/en/4.2/topics/http/shortcuts/#render
render関数の役割 • テンプレートファイルのロード • テンプレートのレンダリング • HttpResponseの作成
render関数を使わない場合 from django.http import HttpResponse from django.template import loader def
my_view(request): template = loader.get_template('spam.html') context = { 'name': 'egg', } return HttpResponse(template.render(context, request)) myapp/views.py
クラスベースビューでテンプレートを使う • django.views.generic.TemplateView • または、TemplateResponseMixinを継承したクラス
from django.views.generic import TemplateView class MyView(TemplateView): template_name = 'spam.html' def
get_context_data(self): context = super().get_context_data() context['name'] = 'egg' return context myapp/views.py from myapp import views urlpatterns = [ path('', views.MyView.as_view()), ] myproject/urls.py
テンプレート言語を使いこなす
テンプレート言語 • レンダリングの際に、テンプレート言語によって出力内容を変 更・制御できる • 変数: {{ 変数名 }} •
フィルター: {{ 変数名|フィルター:パラメータ }} • タグ: {% タグ名 パラメータ1 パラメータ2 ... %} • コメント: {# コメント #} https://docs.djangoproject.com/en/4.2/topics/templates/
テンプレート言語: 変数 • テンプレートに渡されたコンテキストを、テンプレート上で変 数として使用できる。 • {{ 変数名 }} >>>
template = django_engine.from_string("Hello {{ name }}!") >>> template.render({"name": "spam"}) 'Hello spam!'
変数: 辞書やリストへのアクセス def book_view(request): context = { 'book': { 'name':
'Django doc', 'pages': 200, 'tags': ['django', 'python'], }, } return render(request, 'book.html', context) myapp/views.py
name: {{ book.name }}<br> pages: {{ book.pages }}<br> tags: {{
book.tags }}<br> <br> {{ book.tags.0 }} {{ book.tags.1 }} myapp/templates/book.html • 辞書の場合、要素には “.キー名”でアクセスできる • リストの場合も、要素は “.index”でアクセスできる
None
テンプレート言語: フィルター >>> from datetime import datetime >>> template =
django_engine.from_string("Today is {{ value|date:'Y-m-d' }}") >>> template.render({"value": datetime(2023, 10, 7)}) 'Today is 2023-10-07' いろいろなフィルターがある https://docs.djangoproject.com/ja/4.2/ref/templates/builtins/#ref-templates-builtins-filters • 出力する前に、データを処理して、出力内容を変更できる • 変数に対してフィルターを設定する • {{ 変数名|フィルター:パラメータ }}
テンプレート言語: タグ >>> template = django_engine.from_string("Today is {% now 'Y-m-d'
%}") >>> template.render() 'Today is 2023-10-05' いろいろなタグがある https://docs.djangoproject.com/ja/4.2/ref/templates/builtins/#ref-templates-builtins-filters • フィルターと違って、独立した処理、機能を提供する。パラメータには文 字列や変数を指定できる。 • タグ: {% タグ名 パラメータ1 パラメータ2 ... %}
タグによる制御構文: if else endif • テンプレート内で条件分岐を利用できる。 >>> template = django_engine.from_string(
... "{% if value >= 5 %}{{ value }}は5以上{% else %}{{ value }}は5未満{% endif %}" ... ) >>> template.render({"value": 7}) '7は5以上' >>> template.render({"value": 3}) '3は5未満'
タグによる制御構文: for endfor • テンプレート内で繰り返し制御を利用できる。 >>> template = django_engine.from_string("{% for
x in data %}{{ x }}{% endfor %}") >>> template.render({"data": range(5)}) '01234'
タグによる構造化(1): include • 指定したテンプレートファイルを取り込む。 {% include "spam/egg.html" %}
タグによる構造化(2): extends block endblock • テンプレートの継承構造を作れる。 • 継承元のテンプレートでは、blockタグで変更可能なブロック を定義する •
継承したテンプレートでは、blockタグで変更したい部分だけ を定義する
Hello {% block name %}{% endblock %}! base.html {% extends
"base.html" %} {% block name %}bar{% endblock %} bar.html {% extends "base.html" %} {% block name %}foo{% endblock %} foo.html >>> from django.template import loader >>> template = loader.get_template("foo.html") >>> template.render() 'Hello foo!¥n' >>> template = loader.get_template("bar.html") >>> template.render() 'Hello bar!¥n'
Djangoテンプレートをどういうときに使う? • HTML生成のテンプレートとして • メール文章のテンプレートとして • テキスト形式のファイルを生成するテンプレートとして • ユーザーに表示するメッセージのテンプレートとして •
「文字列生成のときに使える」ということを覚えておくとよい
静的ファイルの取り扱い: staticタグ • staticタグを使うと、django.contrib.staticfilesで配信されるファイルのパスを生成できる {% load "static" %} <img src="{%
static "spam/egg.jpg" %}"> • 基本的に、静的ファイルのパスの指定はstaticタグを使う、と考えておけばよい。
リンクのパス生成: urlタグ urlpatterns = [ path("foo/bar/", views.MyView.as_view(), name="my_view"), ] urls.py
• urlタグを使うと、urls.pyで定義したViewのパスを生成できる <a href="{% url "my_view" %}">リンク</a> link.html
コンテキストプロセッサ • 汎用のコンテキストを供給する機能。 • レンダリング時の関数やメソッドにコンテキストを渡さなくて も、テンプレート内でコンテキストプロセッサのコンテキスト を利用できる
コンテキストプロセッサの設定 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], #
任意のテンプレートディレクトリ追加 'APP_DIRS': True, # アプリのtemplatesを使うか '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', ], }, }, ] settings.py
コンテキストプロセッサ: debug • 追加で使えるコンテキスト • debug: デバッグモードが有効かどうか • settings.DEBUG=Trueかつ、REMOTE_ADDRがINTERNAL_IPSに含まれている ものかどうか
• sql_queries: このテンプレートがレンダリングされるまでに実行され たSQLログ
コンテキストプロセッサ: request • 追加で使えるコンテキスト • request: Djangoのrequestオブジェクト(django.http.HttpRequest)
コンテキストプロセッサ: auth • django.contrib.authの機能。認証、権限。 • 追加で使えるコンテキスト • user: ログイン中のユーザー auth.Userまたは、未ログインの場合は
AnonymousUser • perms: 現在ログイン中のユーザーが有するパーミッション
コンテキストプロセッサ: messages • django.contrib.messages(メッセージフレームワーク)の機 能 • 追加で使えるコンテキスト • messages: メッセージフレームワークでセットされたメッセージ一覧。
• DEFAULT_MESSAGE_LEVELS: メッセージレベル名の数値
テンプレートエンジンの カスタマイズ
テンプレートエンジンのカスタマイズポ イント • 自作できるもの • フィルター • タグ • コンテキストプロセッサ
• テンプレートローダー • そもそもテンプレートエンジン自体を差し替えできる • これをやると何でもアリになるのが、ここでは解説しない
フィルターとタグをカスタマイズする準備 • アプリのディレクトリに templatetags という名前のディレクトリを作成 templatetags |--- __init__.py |--- my_customs.py
• 今回は my_customs という名前のモジュールに、カスタムのフィルターとタグを作成す る。 • テンプレート内で有効化するときは、 load タグでロードする。 {% load my_customs %} https://docs.djangoproject.com/ja/4.2/howto/custom-template-tags/
カスタマイズ: フィルター from django import template register = template.Library() @register.filter(name="cut")
def cut(value, arg): return value.replace(arg, "") my_customs.py https://docs.djangoproject.com/ja/4.2/howto/custom-template-tags/#writing-custom-template- filters
カスタマイズ: タグ from django import template register = template.Library() @register.simple_tag
def random_choice(): return value.replace(arg, "") my_customs.py https://docs.djangoproject.com/ja/4.2/howto/custom-template-tags/#writing-custom-template- filters
カスタマイズ: コンテキストプロセッサ • たくさんのページで使う可能性のあるコンテキストを追加した いときに利用 • 注意: コンテキストプロセッサは、テンプレートのレンダリン グ時に毎回実行されるので、遅い処理を入れると全体的に遅く なるかも
• 部分的に使いたいだけであれば、テンプレートタグで十分な場 合が多い
コンテキストプロセッサの作成 import sys def python_version(request): return {'python_version': sys.version} myapp/context_processors.py •
{{ python_version }} のように使える
コンテキストプロセッサの有効化 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS':
True, 'OPTIONS': { 'context_processors': [ ..., # 省略 'myapp.context_processors.python_version', ], }, }, ] settings.py
コンテキストプロセッサの変数を使って みる {{ python_version }} python_version.html
テンプレートローダーについて知る • Djangoテンプレートエンジンが、どこからテンプレートデータ をロードしてくるかを制御する • 組み込みのローダー • django.template.loaders.filesystem: ファイル •
django.template.loaders.app_directories: アプリのtemplatesディレクトリ • django.template.loaders.locmem: ローカルメモリ • django.template.loaders.cached: キャッシュ機能付きローダー https://docs.djangoproject.com/en/4.2/ref/templates/api/#loader-types
テンプレートローダーの設定 TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "OPTIONS": { "loaders":
[ ( "django.template.loaders.filesystem.Loader", [BASE_DIR / "templates"], ), ], }, } ] settings.py
カスタマイズ: テンプレートローダー • 例. データベースからテンプレートをロードする、テンプレー トローダーを自作してみる。 from django.db import models
class Template(models.Model): name = models.CharField(max_length=255) source = models.TextField() myapp/models.py
from django.template.loaders.base import Loader as BaseLoader from django.template import Origin
from .models import Template class DatabaseOrigin(Origin): def __init__(self, name, template_name=None, loader=None, object=None): super().__init__(name, template_name, loader) self.object = object class Loader(BaseLoader): def get_contents(self, origin): return origin.object.source def get_template_sources(self, template_name): template = Template.objects.filter(name=template_name).first() if not template: return [] origin = DatabaseOrigin( name=template_name, template_name=template_name, loader=self, object=template) return [origin] myapp/db_loader.py
テンプレートローダーの設定 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', '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', ], 'loaders': [ (‘myapp.db_loader.Loader’,), # ここを追加 ( ‘django.template.loaders.app_directories.Loader’,), # Django adminなどが動くように ] } }, ] settings.py
None
None
まとめ • Djangoテンプレートエンジンは文字列生成に使う • テンプレートとコンテキストを組み合わせてレンダリングする • テンプレート言語で制御できる • 機能をカスタマイズできる
Django利用状況アンケート実施中! • Googleフォームから回答をお願いします。 • 回答受付期間:2023/10/2(月) ~ 2023/10/16(月) • https://forms.gle/ykQcgtHpWjpods348
ありがとうございました!