Source

djangobook-cn / docs / _build / pickle / _sources / 2.0 / chapter04.txt

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
.. _2.0-chapter04:

===================
第4章: テンプレート
===================

前章で、あなたは私たちの View 例の中でコンテンツを返す方法が
風変わりと気がついたかもしれません。
つまり、以下ように HTML が Python コードとして、
直接ハードコードされていました: 

.. code-block:: python

    def current_datetime(request):
        now = datetime.datetime.now()
        html = "<html><body>It is now %s.</body></html>" % now
        return HttpResponse(html)

このテクニックは、View がどのように動作するか説明するには便利ですが、
あなたの View に直接 HTML をハードコードするのは良い考えでありません。
それには以下の理由があります: 

* ページのあらゆるデザイン変更に、Python コードの変更が必要です。
  サイトのデザインは、内部の Python コードよりも変更が多い可能性が高いため、
  デザインが Python コードを修正する必要なく変更できる方が便利でしょう。

* Python コードを書くことと、HTML のデザインは専門が異なっており、
  プロフェッショナルなウェブ開発環境の多くは、
  別の人(または別の部門)として責任分解しています
  デザイナーと HTML/CSS コーダーは、
  その仕事として Python コードの編集は必要ありません。

* プログラマーが Python コードを書くのと同時に
  デザイナーがテンプレートを書けることは、
  Python と HTML が混在したファイルを1人が書き終わって
  もう1人が書き始めるよりも、はるかに効率的です。

これらの理由により、
ページのデザインを Python コードそのものから切り離すことは、
より美しく、よりメンテナンス性が高くなります。
私たちは、Django のテンプレートシステムでこれを実現できます。
私たちはこの章で、このテンプレートシステムについて解説します。

テンプレートシステムの基礎
--------------------------

Django のテンプレートは、
ドキュメントのデータと、そのプレゼンテーションの分離を目的とした
テキストファイルです。
テンプレートは、プレースホールダと文書が表示されなければならない方法を管理するプレースホルダと必要最低限の基本的なロジック(テンプレートタグ)を定義します。
通常、テンプレートは HTML を生成するために用いますが、
Django のテンプレートは様々なテキストベースのフォーマット
(World Online では、e-mail や JavaScript、 CSV にテンプレートを利用)
も同様に生成できます。

では、単純なテンプレートの例から始めましょう。
この Django テンプレートは、
会社へ発注した人へお礼を言うための HTML ページの説明です。
同文の手紙を出したと仮定して読んでみてください:

.. code-block:: html+django

    <html>
    <head><title>Ordering notice</title></head>

    <body>

    <h1>Ordering notice</h1>

    <p>Dear {{ person_name }},</p>

    <p>Thanks for placing an order from {{ company }}. It's scheduled to
    ship on {{ ship_date | date:"F j, Y" }}.</p>

    <p>Here are the items you've ordered:</p>

    <ul>
    {% for item in item_list %}
    <li>{{ item }}</li>
    {% endfor %}
    </ul>

    {% if ordered_warranty %}
    <p>Your warranty information will be included in the packaging.</p>
    {% else %}
    <p>You didn't order a warranty, so you're on your own when
    the products inevitably stop working.</p>
    {% endif %}

    <p>Sincerely,<br />{{ company }}</p>

    </body>
    </html>

.. admonition:: 日本語の取扱いについて(追記)

    テンプレートに日本語を書くときはエンコードに注意してください。
    デフォルトでは `utf8` になっており、
    テンプレートファイルは `utf8` エンコードで作成する必要があります。
    
    携帯サイト等 `sjis` 使いたい場合は、
    `settings.py` を `DEFAULT_CHARSET = 'sjis'` に設定し、
    テンプレートファイルは `sjis` エンコードで作成してください。

このテンプレートは、基本的な HTML といくつかの変数、
またテンプレートタグから構成されています。
このコードをステップ毎に解説します: 

* 対応する波括弧内にある文字列
  (例えば `{{ person_name }}` )は *変数* です。
  これは "指定された名前の変数の値をここに挿入する" ことを意味しています
  (どのように変数に値を指定するのでしょか?
  私たちはすぐ後でこれを解説します)。

* 波括弧とパーセント記号内にある文字列
  (例えば `{% if ordered_warranty %}` )は *テンプレートタグ* です。
  タグの定義はとても広義に渡ります: 
  タグは、"何かをする" ようにテンプレートシステムに伝えます。

  このテンプレートの例には、 
  `for` タグ( `{% for item in item_list %}` )と 
  `if` タグ( `{% if ordered_warranty %}` )が含まれています。

  `for` タグは Python ステートメントと動作が似ており、
  配列内でループしてアイテムを操作します。 
  `if` タグはあなたが想定している通り、 
  `"if"` ステートメントと同様に動作します。
  この例の場合、タグは `ordered_warranty` 変数の値が `True` かどうかを評価します。
  もし条件に該当する場合は、
  テンプレートシステムは `{% if ordered_warranty %}` から `{% else %}` を表示します。
  もし条件に該当しない場合は、
  テンプレートシステムは `{% else %}` から `{% endif %}` を表示します。
  なお、 `{% else %}` はオプション(なくても大丈夫)です。

* 最後に、このテンプレートの2段落目に *フィルタ* の例が含まれています。
  そして、それは変数のフォーマットを変更する最も便利な方法です。
  この例では、 `{{ ship_date|date:"F j, Y" }}` です。
  私たちは `ship_date` に `date` フィルタを適用し、 
  `date` フィルタのフォーマット引数として `"F j, Y"` を渡しています。
  フィルタは、
  Unix のパイプ( `|` )と同様に、パイプ文字により適用します。

各 Django テンプレートは、
いくつかのビルトインタグとフィルタにアクセスしますが、
それについては後ほど解説します。
「付録 F」は、すべてのタグとフィルタを含むリストであり、
あなたが何が可能かを理解するために、
そのリストに精通するのは良い考えです。
あなたは独自のフィルタとタグを作成することも可能です; 
私たちは、第10章でそれを解説します。

テンプレートシステムの使用
--------------------------

テンプレートシステムがどのように動作するかを見るために、
Django のテンプレートシステムを使ってみましょう - 
しかし私たちは、まだそれを前の章で作成した View に統合しません。
ここでの私たちの目的は、
そのシステムがどのように Django 上で独立して機能するかを解説することです。
(違う言い方をすると: 
通常、あなたは Django の View 内でテンプレートシステムを使用しますが、
私たちはテンプレートシステムがただ Django の View だけでなく、
どこでも使用可能な Python のライブラリーであることを明確にしたいと思っています。)

あなたが Django のテンプレートシステムを、
Python コードとして使用する最も基本的な方法は以下の通りです:

#. 生のテンプレートコードの文字列の `Template` オブジェクトを作成します。

#. `Template` オブジェクトの `render()` メソッドを呼び、
   所定の変数(コンテキスト)をセットします。
   これはコンテキスト内のすべての変数とテンプレートタグに一致する箇所を評価された、
   完全なテンプレート文字列を返します。

このコードは、以下のようになります:

.. code-block:: python

    >>> from django import template
    >>> t = template.Template("My name is {{ name }}.")
    >>> c = template.Context({'name': 'Adrian'})
    >>> print t.render(c)
    My name is Adrian.
    >>> c = template.Context({'name': 'Fred'})
    >>> print t.render(c)
    My name is Fred.

以下のセクションで、各ステップをより詳細に解説します。

テンプレートオブジェクトの作成
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

`Template` オブジェクトをつくる最も簡単な方法は、
その具体例を直接例示することです。 
`Template` クラスは `django.template` モジュールにあり、
そのコンストラクターはテンプレートコード変数を受け取ります。
このコードがどのように動作するかを確認するため、
Python インタラクティブシェルを使ってみましょう。
`django-admin.py startproject` で作成(第2章で解説)
した `mysite` ディレクトリーから、
インタラクティブシェルで `python manage.py` と入力してください。

.. admonition:: 特別な Python プロンプト

    あなたが以前 Python を使ったことがあるのであれば、
    私たちがなぜただ `python` ではなく、 
    `python manage.py shell` を実行するの疑問に思うかもしれません。
    両コマンド共にインタラクティブシェルを開始しますが、 
    `manage.py shell` は、大きな鍵となる違いが1つあります。
    シェルを開始する前に、
    Django に対し、どの設定ファイルを使うのかを伝えます。
    テンプレートシステムを含む多くの Django 部品は、
    あなたの設定ファイルにより動作が決定し、
    どの設定ファイルを使うかが指定されていないフレームワークは利用できません。

    もし、あなたがその具体的な動作を知りたいのであれば、以下のようになっています。
    Django は、インポートパスに置かれた `settings.py` ファイルの、 
    `DJANGO_SETTINGS_MODULE` と呼ばれる環境変数を探します。
    例えば、 `mysite` があなたの Python パス上にある場合、 
    `DJANGO_SETTINGS_MODULE` は `'mysite.settings'` に設定されます。

    あなたが `python manage.py shell` を実行すると、
    このコマンドはあなたのために `DJANGO_SETTINGS_MODULE` の設定を引き受けます。
    あなたがしなければならない最小限の調整と構成をするために、
    私たちはこの例で `python manage.py shell` を使用するのを奨励します。
    
    あなたが Django に詳しくなると、
    あなたは `manage.py shell` ではなく、 
    `DJANGO_SETTINGS_MODULE` を `.bash_profile` 
    または他のシェル環境設定ファイルに設定するでしょう。

いくつか基本的なテンプレートシステムを一通り使ってみましょう:

.. code-block:: python
    >>> from django.template import Template
    >>> t = Template("My name is {{ name }}.")
    >>> print t

もしあなたがインタラクティブを使用しているのであれば、以下のようなものが返されます。

.. code-block:: python

    <django.template.Template object at 0xb7d5f24c>

`0xb7d5f24c` は毎回異なり、何も問題ではありません; 
それは、Python の実装(どうしても知りたいのであれば、
それは `Template` オブジェクトの Python "identity" です)です。

あなたが `Template` オブジェクトを作成すると、
テンプレートシステムはテンプレートコードを、
レンダリングの準備ができた、
内部に最適化された形式に編集します。
しかし、もしあなたのテンプレートコードに構文エラーが含まれていた場合は、 
`Template()` を呼び出すと、 `TemplateSyntaxError` 例外が発生します: 

.. code-block:: python

    >>> from django.template import Template
    >>> t = Template('{% notatag %}')
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
      ...
    django.template.TemplateSyntaxError: Invalid block tag: 'notatag'

ここで `{% notatag %}` は "block tag" と呼ばれています。
"block tag" と "テンプレートタグ" は同義語です。
システムは、以下のどのケースでも、 `TemplateSyntaxError` 例外が発生します:

* 無効なタグ

* 有効なタグに対する無効な引数

* 無効なフィルタ

* 有効なフィルタに対する無効な引数

* 無効なテンプレート構文

* 閉じられていないタグ(タグを閉じることを必要とするタグ)

テンプレートのレンダリング
~~~~~~~~~~~~~~~~~~~~~~~~~~

一度あなたが `Template` オブジェクトを作成すると、
それにコンテキストを与えることによりデータを引き渡すことができます。
コンテキストは、テンプレート変数名とその値のセットです。
テンプレートは、それを内部の変数とそのタグを評価するために使います。
コンテキストは Django の `django.template` モジュールにある、
`Context` クラスがその役割を果たします。
そのコンストラクタは1つの変数を受け取ります: 
変数名を変数値にマップするための辞書です。
テンプレートを対応するコンテキストを渡し、 
`Template` オブジェクトの `render()` メソッドを呼び出す:

.. code-block:: python

    >>> from django.template import Context, Template
    >>> t = Template("My name is {{ name }}.")
    >>> c = Context({"name": "Stephane"})
    >>> t.render(c)
    u'My name is Stephane.'

私たちががここで解説しなければならないポイントは、 
`t.render(c)` の戻り値がユニコードオブジェクトであることです - 
通常の Python 文字列型ではない。
あなたは、文字列の前にある `u` によってこれを見分けることができます。
Django は、フレームワーク内部で標準的な文字列型の代わりに、
ユニコードオブジェクトを使います。
あなたがそれがもたらす影響を理解できるなら、
Django のその内部の洗練された動作に感謝してください。
あなたがその影響を理解できなくても、
今のところ心配しないで大丈夫です; 
Django のユニコードサポートにより、
あなたのアプリケーションが英語の基本的な "A-Z" 以外の、
多種多様な文字セットのサポートに苦労しなくてもいいということを知っておいてください。

.. admonition:: コンテキストと辞書

    Python の辞書は、
    既知の key と 変数 value のマッピングです。 
    `Context` は辞書と似ていますが、 
    `Context` が提供する追加の機能を第10章で解説します。

変数名は英字( A-Z もしくは a-z )で始まり、
数字、アンダーライン(_)、ドット(.)を含むことができます。
(ドットは、特例であり、後で解説します。)
変数名は大文字と小文字を区別します。

この章の始まりで例示したテンプレートを使用した、
テンプレートの編集とレンダリングの例を以下に示します: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> raw_template = """<p>Dear {{ person_name }},</p>
    ...
    ... <p>Thanks for placing an order from {{ company }}. It's scheduled to
    ... ship on {{ ship_date|date:"F j, Y" }}.</p>
    ...
    ... {% if ordered_warranty %}
    ... <p>Your warranty information will be included in the packaging.</p>
    ... {% else %}
    ... <p>You didn't order a warranty, so you're on your own when
    ... the products inevitably stop working.</p>
    ... {% endif %}
    ...
    ... <p>Sincerely,<br />{{ company }}</p>"""
    >>> t = Template(raw_template)
    >>> import datetime
    >>> c = Context({'person_name': 'John Smith',
    ...     'company': 'Outdoor Equipment',
    ...     'ship_date': datetime.date(2009, 4, 2),
    ...     'ordered_warranty': False})
    >>> t.render(c)
    u"<p>Dear John Smith,</p>\n\n<p>Thanks for placing an order from Outdoor
    Equipment. It's scheduled to\nship on April 2, 2009.</p>\n\n\n<p>You
    didn't order a warranty, so you're on your own when\nthe products
    inevitably stop working.</p>\n\n\n<p>Sincerely,<br />Outdoor Equipment
    </p>"

このコードの各行ごとに、そのステップを解説します。

* 最初に、私たちは `django.template` モジュール内にある、 
  `Template` と `Contex` クラスをインポートしています。

* 次に、私たちは `raw_template` 変数にテンプレートの文字列を保存しています。
  私たちは、その文字列が複数行にまたがっているので、
  3つの引用符(ダブルクォート)を使っていることに注意してください;
  Python では、シングルクォート内の文字列は、複数行にまたがることはできません; 

* 次に、私たちは `Template` クラスのコンストラクタに `raw_template` を渡し、 
  `Template` オブジェクト `t` を作成します。

* 次に、私たちが以下の構文で必要とする、 
  `datetime` モジュールを Python 標準ライブラリーからインポートします。

* 次に、私たちは `Context` オブジェクト `c` を作成します。 
  `Context` のコンストラクタは変数名を値にマップする Python 辞書を受け取ります。
  ここでは、私たちは例として `person_name` が 'John Smith' 、 
  `product` が 'Super Lawn Mower' 等を指定しています。

* 最後に、私たちはテンプレートオブジェクトの `render()` メソッドを呼び、
  その引数としてコンテキストを渡しています。
  これは、テンプレートのレンダリング結果を返します - 
  つまり、テンプレート変数を変数値と入れ替え、テンプレートタグを実行します。

  `ordered_warranty` 変数に `False` 値を代入したので、
  "You didn’t order a warranty" 欄が表示されていることに注意して下さい。

  また、日付がフォーマットストリング `'F j, Y'` により、 
  `April 2, 2009` と表示されていうことに注意してください。
  (私たちは、 `date` フィルターへの日付フォーマット文字列について後ほど解説します。)

  あなたが Python をあまり使ったことがないのであれば、
  この出力がなぜ表示内で改行されず、
  改行文字(`\n`)が含まれるか疑問に思うかもしれません。
  それは、Python インタラクティブシェルの微妙な部分です: 
  `t.render(c)` を呼び出すと文字列を返しますが、
  インタラクティブシェルは標準で文字列でなく、
  文字列表現を出力します。
  あなたが、 `\n` 文字でなく本来の改行として文字列を出力したいのであれば、 
  `print` 構文を利用してください: `print t.render(c)` 。

これが、Django テンプレートシステムを使用するための基礎です: 
テンプレート文字列を書き、 
`Template` オブジェクトを作成し、 
`Context` を作成し、
`render()` メソッドを呼びます。

同じテンプレートへの複数のコンテキスト
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

あなたが一度 `Template` オブジェクトを作成すると、
あなたはそれにより複数のコンテキストをレンダリングすることができます。
例えば: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> t = Template('Hello, {{ name }}')
    >>> print t.render(Context({'name': 'John'}))
    Hello, John
    >>> print t.render(Context({'name': 'Julie'}))
    Hello, Julie
    >>> print t.render(Context({'name': 'Pat'}))
    Hello, Pat

このように、あなたが同じテンプレートソースを複数のコンテキストでレンダリングするには、 
*一度* `Template` オブジェクトを作成し、
それから `render()` を複数回呼び出すのが効率的です:

.. code-block:: python

    # Bad
    for name in ('John', 'Julie', 'Pat'):
        t = Template('Hello, {{ name }}')
        print t.render(Context({'name': name}))

    # Good
    t = Template('Hello, {{ name }}')
    for name in ('John', 'Julie', 'Pat'):
        print t.render(Context({'name': name}))

Django のテンプレートパーサーは非常に高速です。
内部でのパース(構文解析)のほとんどは、単一の正規表現を呼び出します。
これはXMLベースのテンプレートエンジンとまったく正反対です。
XMLパーサーはオーバーヘッドに陥るため、
Django のテンプレートレンダリングエンジンより遅くなる傾向があります。

コンテキスト変数の参照
~~~~~~~~~~~~~~~~~~~~~~

これまでの例では、
私たちのコンテキストは単純な値でした - 
文字列や `datetime.date` の例。
しかし、テンプレートシステムは洗練されており、
リストや辞書、カスタムオブジェクト等複雑なデータ構造を取り扱うことができます。 

Django テンプレートで複雑なデータ構造を利用する鍵はドット文字(`.`)です。
辞書の key、属性、インデックス、オブジェクトのメソッドへのアクセスにドットを使ってください。

この最もわかりやすい例をいくつか示します。
例えば、あなたがテンプレートに Python の辞書を渡すと仮定してください。
辞書の key でその辞書の value にアクセスするためにドットを使います: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> person = {'name': 'Sally', 'age': '43'}
    >>> t = Template('{{ person.name }} is {{ person.age }} years old.')
    >>> c = Context({'person': person})
    >>> t.render(c)
    u'Sally is 43 years old.'

同様に、ドットはオブジェクトの属性にアクセスできます。
たとえば、Python `datetime.date` オブジェクトには、 
`year` 、 `month` 、 `day` 属性があり、
あなたは Django テンプレートでその属性にアクセスするためにドットを使うことができます: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> import datetime
    >>> d = datetime.date(1993, 5, 2)
    >>> d.year
    1993
    >>> d.month
    5
    >>> d.day
    2
    >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
    >>> c = Context({'date': d})
    >>> t.render(c)
    u'The month is 5 and the year is 1993.'

以下の例はカスタムクラスを使用しており、
任意のオブジェクトの変数にドットでアクセスできることを表しています: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> class Person(object):
    ...     def __init__(self, first_name, last_name):
    ...         self.first_name, self.last_name = first_name, last_name
    >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
    >>> c = Context({'person': Person('John', 'Smith')})
    >>> t.render(c)
    u'Hello, John Smith.'

ドットはオブジェクトのメソッドを参照することができます。
たとえば、各 Python 文字列は `upper()` や `isdigit()` メソッドを持っており、
あなたは同じドット構文を利用し Django テンプレートでそれを呼ぶことができます: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
    >>> t.render(Context({'var': 'hello'}))
    u'hello -- HELLO -- False'
    >>> t.render(Context({'var': '123'}))
    u'123 -- 123 -- True'

あなたは、メソッドの呼び出しに括弧を含めないことに注意すべきです。
また、メソッドに対して引数を渡すことはできません; 
あなたは属性を必要としないメソッドのみを呼ぶことができます。
(私たちは、この章の最後にこの思想を解説します。)

最後の例として、ドットはリストのインデックスへのアクセスにも使われます: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> t = Template('Item 2 is {{ items.2 }}.')
    >>> c = Context({'items': ['apples', 'bananas', 'carrots']})
    >>> t.render(c)
    u'Item 2 is carrots.'

負のリストインデックスは許可されていません。
たとえば、テンプレート変数 `{{ items.-1 }}` は、 
`TemplateSyntaxError` が発生します。

.. admonition:: Python リスト

    注意: Python リストのインデックスは 0 から始まります。
    最初のアイテムのインデックスは 0 で、2番目のインデックスは 1、と続きます。

ドットによる参照は、以下のようにまとめることができます: 
テンプレートシステムが変数名にドットを見つけると、それは以下の順序で参照を試みます: 

* 辞書参照(例えば、 `foo["bar"]` )
* 属性参照(例えば、 `foo.bar` )
* メソッド参照(例えば、 `foo.bar()` )
* リスト-インデックス参照(例えば、 `foo[bar]` )

システムは、動作する最初の参照タイプを利用します。
それはロジックを短縮させます。
ドットによる参照は、複数階層に深く入れ子してるかもしれません。
例えば、以下の例では `{{ person.name.upper }}` が使われており、
最初に辞書参照( `person['name']` )し、
その後メソッドを呼び出し( `upper()` )ています: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> person = {'name': 'Sally', 'age': '43'}
    >>> t = Template('{{ person.name.upper }} is {{ person.age }} years old.')
    >>> c = Context({'person': person})
    >>> t.render(c)
    u'SALLY is 43 years old.'

メソッド呼び出しの動作
``````````````````````

他の参照タイプより、メソッドの呼び出しは少し複雑です。
以下のことを心に留めておいてください。

* メソッド参照をしている間に、
  メソッドで例外が発生した場合、
  例外の `silent_variable_failure` 属性が `True` でない限り、
  例外が通知されます。
  例外に `silent_variable_failure` 属性がある場合、
  変数は空文字列をレンダリングします。
  例えば: 

  .. code-block:: python

      >>> t = Template("My name is {{ person.first_name }}.")
      >>> class PersonClass3:
      ...     def first_name(self):
      ...         raise AssertionError, "foo"
      >>> p = PersonClass3()
      >>> t.render(Context({"person": p}))
      Traceback (most recent call last):
      ...
      AssertionError: foo

      >>> class SilentAssertionError(AssertionError):
      ...     silent_variable_failure = True
      >>> class PersonClass4:
      ...     def first_name(self):
      ...         raise SilentAssertionError
      >>> p = PersonClass4()
      >>> t.render(Context({"person": p}))
      u'My name is .'

* メソッド呼び出しは、メソッドに必須属性がない場合にのみ動作します。
  そうでない場合、システムは次の参照タイプであるリスト-インデックス参照に移ります。

* 当然いくつかのメソッドには副作用があり、
  テンプレートシステムからのアクセスを許可されるため、
  馬鹿馬鹿しいですが、考え方によってはセキュリティホールになりえます。

  例えば、あなたが `BankAccount` オブジェクトに `delete()` メソッドを持たせたとしましょう。
  テンプレートから、 
  `{{ account.delete }}` のようなメソッドにアクセスを許可するべきではありません。

  これを防ぐために、メソッド内に `alters_data` 関数属性を指定してください。

  .. code-block:: python

      def delete(self):
          # Delete the account
      delete.alters_data = True

  テンプレートシステムは、このようにマークされたあらゆるメソッドを実行しません。
  言い換えると、もしテンプレートに `{{ account.delete }}` が含まれても、
  そのタグは `delete()` タグを実行しません。
  それは、何もせず失敗します。

無効な変数の取扱い
``````````````````

デフォルトの変数が存在しない場合、
テンプレートシステムはそれを空文字列としてレンダリングし、何もせず失敗します。
例えば: 

.. code-block:: python

    >>> from django.template import Template, Context
    >>> t = Template('Your name is {{ name }}.')
    >>> t.render(Context())
    u'Your name is .'
    >>> t.render(Context({'var': 'hello'}))
    u'Your name is .'
    >>> t.render(Context({'NAME': 'hello'}))
    u'Your name is .'
    >>> t.render(Context({'Name': 'hello'}))
    u'Your name is .'

その原因が人為的ミスによることが多いので、
システムは例外を通知せず、何もせずに失敗します。
この場合、変数名には間違ったケースや名前があるため、全ての参照に失敗します。
現実的に、Web サイトが小さなテンプレート構文エラーのために理解できなくなるのは歓迎できません。
あなたの Django の構成で設定を変更することにより、
Django のこのデフォルトのふるまいを変更できることに注意すべきです。
私たちは、これについて第10章で解説します。

コンテキストオブジェクトの操作
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

ほとんどの場合、
あなたは `Context` に完全に含む辞書を渡すので、 
`Context()` オブジェクトの具体例をあげて示します。
しかし、標準的な Python 辞書構文を使用すると、
あなたは `Context` オブジェクトからアイテムの追加・削除を行うことができます: 

.. code-block:: python

    >>> from django.template import Context
    >>> c = Context({"foo": "bar"})
    >>> c['foo']
    'bar'
    >>> del c['foo']
    >>> c['foo']
    Traceback (most recent call last):
      ...
    KeyError: 'foo'
    >>> c['newvariable'] = 'hello'
    >>> c['newvariable']
    'hello'