Django
のクラスベースビューのメソッド内でURLのパラメータを取る。
listview
のメソッド、get_queryset(self)
内でURLのパラメータを取得したい。
結論
結論から述べると、メソッド内で、self.kwargs
を使えばいい。
# 結論
def get_queryset(self):
# self.kwargs.get()を使う。第二引数はデフォルト値。
year = self.kwargs.get('year', 2000)
month = self.kwargs.get('month', 10)
day = self.kwargs.get('day', 10)
return self.create_result(year, month, day)
以下、経緯。
経緯
urls.py
は次のようになっている。
# urls.py
urlpatterns = [
path(
'path/to/<int:year>/<int:month>/<int:day>/',
views.SomeListView.as_view(),
name='list',
),
...
]
views.py
は次のようになっている。
class SomeListView(ListView):
model = models.SomeModel
context_object_name = 'some_models'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
return context
def get_queryset(self):
return self.model.objects.all()
SomeListView
内のメソッドで、URLのyear
,month
,day
を使いたい。
get_queryset
内でフィルタに使いたい。
公式docsを見ても、情報は見つからない。探し辛くもある。
なので、ソースを眺めたところ、全てのビューの基底クラスのdjango.views.generic.base.View
で
参考になりそうなものがあった。
as_view
クラスメソッドにある。このメソッドは、urls.py
で登録するやつ。view関数を生成してくれる。
その生成する関数が以下のようになっていた。
def as_view(...):
...
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
...
return view
このview
関数インスタンスが関数ベースビューで定義してた関数と同等のものになる。
関数ベースビューの時は、パラメータはrequest引数の後に書いていた。
なので、*args
と**kwargs
が怪しい。
そして、それらはself
のフィールドに格納されてる。
そのフィールドにアクセスすれば良さそう。試してみる。
# 実験用コード1
def get_queryset(self):
print(self.kwargs)
print(self.args)
# stub
return self.model.objects.all()
これでページにアクセスすれば、出力されるはず。
localhost:8000/path/to/2019/1/1/
にアクセスすると、次のように出力された。
# 実験用コード1の出力
{'year': 2019, 'month': 1, 'day': 1}
()
self.kwargs
を見れば良いことがわかる。取り出しを見てみる。
# 実験用コード2
def get_queryset(self):
# urls.pyの内容からして、デフォルトは使われないはず。
default_year = 2000
print(self.kwargs.get('year', default_year))
# stub
return self.model.objects.all()
localhost:8000/path/to/2019/1/1/
にアクセスした時、出力は次のようになる。
# 実験用コード2の出力
2019
OK。デフォルトは指定しなくても問題ない。
また、get_context_data
など、フローチャート(公式docs用語)内のどのメソッドからも参照できるはず。
あとがき
もう少し公式docs見やすくなってほしい。せめて検索が検索になってほしい。
コメント