#21964 closed Cleanup/optimization (wontfix)

ProcessFormView should pass **kwargs to get_context_data()

Reported by: cjerdonek Owned by: nobody
Component: Generic views Version: 1.6
Severity: Normal Keywords:
Cc: chris.jerdonek@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In the ProcessFormView class, keyword arguments to the view aren't available in the template context by default.

From what I can tell, changing this behavior (so that one can customize other aspects of the template) requires relying on undocumented implementation details of Django views (namely that View.as_view() sets self.kwargs). For example:

def get_context_data(self, **kwargs):
    # ProcessFormView doesn't pass the view's keyword arguments in its
    # calls to get_context_data(), so we need to add them back manually.
    context = self.kwargs.copy()
    context.update(kwargs)
    return context

I think things would be simpler and more consistent if ProcessFormView passed the view's **kwargs to get_context_data() in the first place, in which case ProcessFormView could implement its own version of get_context_data() that would restrict the context. This would be more DRY by eliminating the need to read self.kwargs when overriding get_context_data(). This will also reduce potential confusion between the **kwargs argument and the undocumented self.kwargs attribute.

Change History (5)

comment:1 Changed 19 months ago by cjerdonek

  • Cc chris.jerdonek@… added
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 19 months ago by timo

  • Component changed from Uncategorized to Generic views

FWIW, pushing kwargs to the context has been called an anti-pattern in #19878 and we're planning to deprecate that behavior in TemplateView. I guess this change may still have merit, but I haven't looked into the details.

comment:3 Changed 19 months ago by cjerdonek

Thanks for the pointer to the current thinking. In that case, it seems like self.kwargs should be documented somewhere as the recommended way to access the keyword arguments passed to a view (as opposed to **kwargs to whatever method is being overridden). Currently, self.kwargs is set by as_view() here. One place self.kwargs could be documented is in the attributes subsection of the django.views.generic.base.View documentation. It doesn't currently seem to be documented anywhere that I've come across. Maybe the documentation for as_view() could also include a note about setting self.kwargs.

comment:4 Changed 19 months ago by cjerdonek

Sorry, scratch my last comment. I misread your comment that "pushing kwargs to the context has been called an anti-pattern" as saying "pushing kwargs to get_context_data() has been called an anti-pattern." self.kwargs need not be documented if the view's keyword arguments are passed to get_context_data() as I suggested in this issue.

comment:5 Changed 19 months ago by mjtamlyn

  • Resolution set to wontfix
  • Status changed from new to closed

The self.kwargs attribute is documented (https://docs.djangoproject.com/en/dev/topics/class-based-views/generic-display/#dynamic-filtering), however this is not the most obvious location for the documentation.

The understanding with get_context_data is that kwargs will put in the context. Automatically passing the url kwargs into the context (from get() or similar) is an antipattern (#19878). If you really wish to access them, you can access view.kwargs in the context as the view instance is passed into the context.

If you feel strongly that we should improve the documentation of self.args and self.kwargs, and have a concrete proposal on where to do so, please open a new ticket.

Note: See TracTickets for help on using tickets.
Back to Top