2025年12月17日水曜日

Django の標準URLの動作

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変数名:key を指定している
    しかし、DetailViewが探している名前:pk

pk を期待しているのに、key と<int:key> と指定しているためです。
もちろんこのようなしてでも問題はありませんが、下記のように指定することにより正しく扱われることになります。

class stationView(DetailView):
    model = station
    pk_url_kwarg = "key"

このように指定することにより、Djangoは「URLの key を pk として使えばいいんだな」と考えてくれます。
下記の表を参考にしながら、コーディングしましょう。

URLconf
DetailView設定
結果
<int:pk>
何も書かない
✅ OK
<int:key>
何も書かない
❌ エラー
<int:key>
pk_url_kwarg="key"
✅ OK
<slug:slug>
slug_field + slug_url_kwarg
✅ OK


slug の場合は?
        URLConf
path("info/<slug:slug>/", ...)

            Views 

class StationNameView(DetailView):
    slug_field = "slug"
    slug_url_kwarg = "slug"

    • URL変数名 ≠ slugslug_url_kwarg が必要
    • 一致していれば省略可能
      という動作となります
まとめ

なぜ Django は pk を固定で探すのか?

理由は 慣例と安全性です。

  • ほとんどの DetailView は <int:pk> を使う

  • 初心者が迷わないよう、デフォルトを固定している

  • 明示したい場合だけ pk_url_kwarg を指定する


0 件のコメント: