はじめに
Django で EC サイトを作成している中で、
「テンプレートに住所の一部だけがどうしても表示されない」
という謎のバグにハマったので、原因と対処法をまとめておきます。
問題
購入者の住所をテンプレートに表示しようとしたところ、
「都道府県」「市区町村」は表示されるのに、途中の一部だけ表示されないという状態になりました。
<tr>
<th>住所</th>
<td>
{{ customer.prefecture }} {{ customer.city }} {{
customer.street_address }} {{ customer.building_name }}
</td>
</tr>
調査で試したこと
まずは、よくあるミスを一通り疑いました。
- テンプレートタグの全角・半角を確認
{{ customer.street_address }} が全角の { } になっていないか確認
→ 問題なし
データベースの中身を確認
- 管理画面やシェルから street_address に値が入っているか確認
→ 問題なし
モデルのフィールド名を確認
- models.py のフィールド名とテンプレートの変数名が一致しているか確認
→ 問題なし
ここまで調べても原因がわからず、「なぜか一部だけ出ない」という状態…。
一旦、原因を切り分けるために、
同じフィールドをテンプレート上で連続して出力してみました。
<tr>
<th>住所</th>
<td>
{{ customer.prefecture }} {{ customer.city }} {{
customer.street_address }}{{ customer.building_name }}{{
customer.street_address }}{{ customer.street_address }}
</td>
</tr>
すると、こんな現象が起きました。
-
同じ street_address を複数回書いているのに、一部だけ表示される
-
しかも、VSCode の自動整形で改行が入った位置のものだけ表示されていない
ここでようやく、
「もしかして VSCode の自動整形で、テンプレートタグの区切りがおかしくなっているのでは?」
という仮説にたどり着きました。
実際に観察してみると、
VSCode のフォーマッタが {{ ... }} の途中で改行を入れた箇所だけ、出力されていない ことが分かりました。
解決策
VSCode の自動整形を毎回オフにするのは正直面倒なので、
テンプレート側をいじるのではなく、モデル側で住所を組み立てるプロパティを用意する 方針にしました。
# 請求情報モデル
class Checkout(models.Model):
class Meta:
db_table = "checkout"
# 登録順に並べる
ordering = ["-created_at"]
# 省略
prefecture = models.CharField("都道府県", max_length=30)
city = models.CharField("市区町村", max_length=30)
street_address = models.CharField("丁目・番地・号", max_length=30)
building_name = models.CharField("建物名・部屋番号", max_length=30, blank=True)
# 完成系の住所を作成する
@property
def full_address(self):
parts = [
self.prefecture,
self.city,
self.street_address,
self.building_name or "",
]
return " ".join(p for p in parts if p)
テンプレートでは full_address を呼ぶだけにします。
<tr>
<th>住所</th>
<td>
{{ customer.full_address }}
</td>
</tr>
無事表示させることができました!
上記のような処理ができない場合
上記のような対応ができないケースが出てくる場合があるかと思います。
その際は、自動整形を無視させたいブロックの上でこの記述(<!-- prettier-ignore -->)をするとそのブロックのみ自動整形を無視させることができます。
最後に
今回のケースから得た学びをまとめると、こんな感じです。
-
VSCode などの自動整形ツールがテンプレートタグの途中で改行を入れると、想定外の挙動をすることがある
-
テンプレートのロジックを複雑にしすぎると、フォーマッタとの相性問題にもハマりやすい
-
住所のように「組み立てロジック」が発生するものは、モデル側で @property を使って「完成形」を返す設計にすると、安全かつ再利用もしやすい


