Classed Based Views : Why do URL parameters in Django/DRF go into `self.kwargs` instead of another attribute (e.g., `self.url_params`)?
While working with Django/Django Rest Framework, I noticed an inconsistency in how URL parameters are acccessed in class-based-views.
Problem Description
In Generic Class Based Views, I can access URL parameters in two different ways - depending on the method:
- Trough the positional arguments:
For example in the
get
method, I can access URL parameters as a positional arguments passed directly to method:
#urls.py
path('test/<str:param1>/<int:param2>/', MyView.as_view())
#views.py
class MyView(View):
def get(self, request, param1, param2):
return JsonResponse({'param1': param1, 'param2': param2})
- Trough
self.kwargs
attribute For example when i want to access the same parameters in theget_queryset
method, I have to useself.kwargs
#views.py
class MyView(ListView):
model = MyModel
def get_queryset(self):
param1 = self.kwargs.get('param1')
param2 = self.kwargs.get('param2')
return MyModel.objects.filter(field1=param1, field2=param2)
I know that i can access url parameters from kwargs
anywhere but it leads me to some questions
My questions:
- Why didn't Django/DRF introduce a dedicated attribute for URL parameters ? Wouldn't it be more intuitive to have these parameters stored in dedicated attribute such as
self.url_params
- are there any specific reasons whyself.kwargs
nameing is preferred - i got the convention but its a bit confusing for me, we got a lot of others attributes such as idkself.data
orself.method
, but we don't have one for url attributes. - Why is the
self.kwargs
mechanism not explicity explained in Django's documentation. I had a bit of a headache, when I was trying to figure out why. The mechanism seems crucial for working with class-based views, yet I couldn't find a clear explanation of why is that. Instead the documentation only provides examples, seemingly expecting developers to "infer" that URL parameters are stored in self.kwargs.
Can anyone shed some light on why this is the case? I’d appreciate any insights or explanations about this design decision.