Django のDetailViewを扱うときのテクニック
DetailView は内部で次のように考えています:
-
URLから
pkという名前の引数 を探す -
なければ
slugという名前の引数 を探す -
どちらも無ければ エラー
内部ロジック(イメージ):
pk = self.kwargs.get("pk")
slug = self.kwargs.get("slug")
if not pk and not slug:
raise AttributeError("Generic detail view must be called with either an object pk or a slug")
通常は、URLConfで主キーに「pk」またはslug を指定してあると見ます。
そのため、次のようにURLConfで上記の名称を使わないとエラーとなります。
path("info/<int:key>/", views.stationView.as_view())
Djangoの標準動作では、
URL変数名:
URL変数名:
key を指定している しかし、DetailViewが探している名前:
pk
pk を期待しているのに、key と<int:key> と指定しているためです。
もちろんこのようなしてでも問題はありませんが、下記のように指定することにより正しく扱われることになります。
class stationView(DetailView):model = stationpk_url_kwarg = "key"
このように指定することにより、Djangoは「URLの
key を pk として使えばいいんだな」と考えてくれます。下記の表を参考にしながら、コーディングしましょう。
URLconf | DetailView設定 | 結果 |
|---|---|---|
| 何も書かない | ✅ OK |
| 何も書かない | ❌ エラー |
|
| ✅ OK |
|
| ✅ OK |
slug の場合は?
URLConf
path("info/<slug:slug>/", ...)
Views
class StationNameView(DetailView):slug_field = "slug"slug_url_kwarg = "slug"
- URL変数名 ≠
slug→slug_url_kwargが必要 - 一致していれば省略可能
という動作となります
まとめ
なぜ Django は pk を固定で探すのか?
理由は 慣例と安全性です。
-
ほとんどの DetailView は
<int:pk>を使う -
初心者が迷わないよう、デフォルトを固定している
-
明示したい場合だけ
pk_url_kwargを指定する