djangoでurlpatternを使いこなしたいけど、良くわからない。
という方に向けて、urlpatternを使いこなす方法について詳しく解説していきます。
Djangoのレベルを高めていきましょう。
まずは基本の形をおさえる
一応復習です。Djangoの基本形を簡単に復習しておきましょう。
コードurlpatterns = [
path('functionview/', somefunc),
path('classview/', SomeFunc.as_view()),
]
上記のurlpatternの場合、functionviewというurlがリクエストされるとsomefuncという関数が呼びだれます。
そして、classviewというurlがリクエストされると、classviewというクラスが呼び出されます。
上記のurlpatternをベースに、いろいろなパターンでviewを呼び出せるようにすることがこの記事の目的です。
まずはfunction based viewから
まずはfunction based viewの場合から見ていきましょう。
function based viewの場合、パラメーターを入れると任意のurlでviewが呼び出される
まず押さえておきたいことは、function based viewの場合はパラーメータをurlに入れると、どのようなurlであっても基本的にはviewが呼びだされるという点があります。
と言ってもこれでは良く分からないと思いますので、具体的な例でみていきましょう。
以下のようなurlpatternがあったとします。
コードurlpatterns = [
path('functionview/<pk>', somefunc),
]
この時、functionview/10と入力しても、functionview/1001と入力しても、functionview/12345678と入力してもviews.pyファイルのsomefuncが呼び出されます。
views.pyファイルでの設定
ただし、上記の形でviewを呼び出すためには、一つだけ設定をしなければいけません。
それは、urlpatternsで設定したpkをviewの中で受け取るための設定です。
具体的には、somefuncを呼び出すときに以下のようにpkを指定してあげる必要があります。
コード-views.py
def somefunc(request, pk):
return HttpResponse('')
なぜこのような設定をしなければいけないのかというと、urlpatternsで入力したpkというのは、キーワード引数のkeyとして使われるからです。
イメージで解説してみました。以下のイメージをご覧ください。
viewを呼び出す文字列と、キーワード引数のpkは全く違うものとして使われていることが分かります。
キーワード引数を使ってデータを取る方法
function based viewの場合は、以下のようなコードを書くことによって、urlで入力されたキーワードに対するデータを取得することができるようになります。
コード-views.py
def somefunc(request, pk):
data = Model.objects.get(pk=pk)
return HttpResponse('')
data = Model.objects.get(pk=pk)という部分に注目してください。
これは、Modelクラスのオブジェクトの中で、モデルのpkがキーワード引数のpk(今回の場合は100)であるデータを取り出して、それをdataに格納しているということを意味しています。
このように、データを指定することでモデルから意図するデータを取り出すことができるということを頭に入れておきましょう。
他のパラメーターでも基本的には同じ考え方
ここまでの例ではpkを例にしてお話をしてきましたが、これは違うパラメーターでも同じように考えることができます。
コードurlpatterns = [
path('functionview/<username>', somefunc),
]
今回は、usernameという名前を定義しました。
コード-views.py
def somefunc(request, username):
data = Model.objects.get(username=username)
return HttpResponse('')
そして、このように設定することによって、指定したusernameに対応したデータを取り出すことができるようになります。
重複したデータがある場合、エラーになる
一つ意識しておきたい点として、取り出すデータが重複している場合はエラーが出る、ということが挙げられます。
つまり、上記のusernameの場合では、モデルに入っているusernameのデータで、例えばtaroという人が2人以上いる場合、エラーになってしまいます。
複数のパラメーターを設定することも可能
urlpatternを設定するときには、複数のパラメーターを設定することも可能です。
例えば、以下のようなurlpatternがあったとしましょう。
コードurlpatterns = [
path('functionview/<username>/<pk>', somefunc),
]
この場合に対応したviewは以下になります。
コード-views.py
def somefunc(request, pk, username):
data = Model.objects.get(pk=pk, username=username)
return HttpResponse('')
複数のパラメーターも扱うことができる。という点は頭に入れておくとよいかもしれません。
class based viewの場合
次に、class based viewの場合をみていきましょう。
これもコードを下記ながら理解していった方が分かりやすいと思いますので、早速コードを書いていきましょう。
まずはurlpatternからです。
コードurlpatterns = [
path('classview/', SomeFunc.as_view()),
]
次に、models.pyファイルを作っていきましょう。
コードclass SomeModel(models.Model):
title = models.TextField()
titleというデータフィールドを定義したモデルを作りました。
次に、views.pyファイルを作っていきましょう。
コードclass SomeFunc(DetailView):
template_name = 'detail.html'
model = SomeModel
ここでのポイントは、SomeFuncの中で使うモデルとしてSomeModelを指定していることです。
これで最低限の設定は完了です。
次から実際にurlにパラメーターを入れていきましょう。
パラメーターと表示内容
まず、urlpatternを以下のようにした場合についてみていきます。
コードurlpatterns = [
path('classview/<pk>', SomeFunc.as_view()),
]
このように設定をした上で、以下のようなurlをリクエストしたとします。
https://localhost:8000/classview/10
すると、SomeModelの中からprimary keyが10番のデータがobjectという変数の中に格納されます。
function based viewのように明示的にオブジェクトを取り出していないので、イメージが湧きづらいのですが、内部でやっていることは同じということを頭に入れておくと良いかもしれません。
class based viewの場合、pkかslugを使う必要がある
ただし、class based viewの場合におさえておくべきこととして、少なくともpkかslugを使う必要があるということが挙げられます。
これも具体的なコードで見ていきましょう。
以下のようなurlpatternを設定したとしましょう。
コードurlpatterns = [
path('classview/<title>', SomeFunc.as_view()),
]
このように設定したとしましょう。上記のurlで指定したtitleというのは、SomeModelの中で定義したtitleフィールドです。
ですので、モデルに入っているデータのtitleをurlに入れればうまく行きそうなのですが、リクエストをすると以下のような表示が返ってきます。
一番上の英語の部分を訳すと、「detailviewは、pkかslugを使って呼び出されなければいけない」と書かれています。
つまり、任意で設定したフィールド(今回の場合はSampleModeで定義したtitleフィールド)を使って特定のデータを取り出すことはできないのです。
ですので、このエラーを回避するためには、urlpatternを以下のように設定する必要があります。
コードurlpatterns = [
path('classview/<pk>/<title>', SomeFunc.as_view()),
]
この時、pkがモデルの中のデータと合っていれば、<title>タグは何であっても問題ありません。
つまり、以下のようなurlのいずれも、同じデータを取り出すことができるのです。
コードhttps://localhost:8000/classview/10/abcd
https://localhost:8000/classview/10/タイトル
https://localhost:8000/classview/10/あああ
このように、あくまでもpkかslugの情報によって、呼び出すviewを決めているということを頭に入れておきましょう。
urlのまとめ
(1) urlに打ち込んだ情報が、キーワード引数としてviewに渡される
(2) 複数の引数を指定することも可能
(3) class based viewの場合はpkかslugを使ってデータと紐づけることができる