queryset - django tutorial
Manejo de los argumentos clave kwargs en las vistas basadas en clases de Django(CBV) (1)
Me acerqué peligrosamente a la locura cuando (al ser un principiante de Django) no pude acceder a un objeto modelo por medio de la clave primaria pk
(proveniente de la URL) en mi subclase FormView
e intenté entender cómo hacerlo bien . Es confuso.
Entonces, ¿cómo se pasan los argumentos de las palabras clave en los CBV genéricos y cómo se deben manejar y usar?
(Y voy a contestarme a mí mismo, porque lo descubrí y lo escribí para entenderlo correctamente).
No confundas kwargs
con esos otros kwargs
...
- Recuerde que una vista eventualmente siempre es una función. Como puede recordar de "Cómo procesa Django una solicitud" , los grupos sin nombre de la expresión regular urlconf se pasarán a la vista como
*args
y los grupos nombrados como**kwargs
. - Pero para un CBV es menos obvio cuál es esa función de vista en realidad o qué hace, porque está oculta profundamente en Django. Como recordará de "Uso de vistas basadas en clases" , la función
as_view()
un CBV creará y devolverá la función de vista real. - Así que aquí es lo primero que hay que recordar sobre el manejo de
kwargs
: enurls.py
, cuando escribes algo comoMyView.as_view(myarg=myvalue)
, cada argumento de palabra clave anulará el atributo de clase con el mismo nombre de la clase CBV en el CBV ejemplo. Esos argumentos se conocen comoinitkwargs
. - La función de vista que realmente se ejecutará (vamos a llamarlo
vvv
) es una genérica definida en django.views.generic.base . Crea una instancia de su CBV, pasa losinitkwargs
al constructor, almacena larequest
,*args
y**kwargs
en los mismos atributos en la instancia CBV, y finalmente llama adispatch()
en la instancia. - Y aquí viene uno de esos detalles confusos: los mismos argumentos
request
,*args
y**kwargs
también serán pasados adispatch()
directamente. (Escribo llamada parens para indicar métodos en oposición a los atributos de datos; los parientes vacíos no significan que no hay argumentos). -
dispatch()
examina la solicitud y llama aget()
,post()
,head()
etc., según el tipo de solicitud, pasando de nuevo los argumentos. - Y hay más redundancia a la vuelta de la esquina: los
initkwargs
se almacenan de forma redundante envvv.view_initkwargs
. (Trate de olvidar esto rápidamente, rara vez lo necesitará). - Una vez que se llama a la vista así creada, los
kwargs
"reales" se pasan a varios métodos de manejo de solicitudes en las diversas subclases de vista genéricas y se ven las clases mixin. La estructura de esas clases, sin embargo, puede volverte loco. Si está interesado en preservar su salud mental, le recomiendo usarvanilla-views
como reemplazo de los CBV genéricos incorporados de Django. El paquete proporciona las mismas capacidades en una forma mucho más simple. - Entonces, para resumir: hay (1)
initkwargs
que se derivan de los argumentos de palabra clave individuales para el método de fábrica de vistaas_view()
y terminarán como atributos individuales de la instancia de clase CBV y (2)kwargs
que provienen de grupos con nombre en su instancia de urlconf y termina como (2a) argumentos de palabra clave para las llamadas a sus métodosget()
ypost()
así como, confusamente, (2b) un atributokwargs
en su instancia de clase CBV. - Entonces, ¿ cuál debería usar , el argumento
kwargs
o el atributo? Esta publicación argumenta que el uso del atributo es más natural para un CBV y que también hará que el código sea más uniforme, porque el argumento no está disponible en todos los lugares dentro del marco CBV. - Y esta es la fuente final de la confusión: los métodos para los que no se
kwargs
loskwargs
a menudo sí tienen un parámetrokwargs
sí mismos ...
Moral: Prefiera self.kwargs
sobre el argumento kwargs
siempre que sea posible y no permita que initkwargs
confunda.