Summary
WizardView defines get_context_data() with the following signature:
def get_context_data(self, form, **kwargs)
However, in its superclass TemplateView (or, specifically, ContextMixin) it has the following signature:
def get_context_data(self, **kwargs)
This means that the override in WizardView is incompatible because it breaks the Liskov substitution principle: form is required by WizardView, but not by TemplateView.
Why it matters
-
Code designed to work with any TemplateView (such as a mixin that overrides get_context_data() to add an additional entry) may not work with WizardView.
-
When the user overrides get_context_data() in a WizardView, type checkers like Ty complain about the override being incompatible, no matter whether you define it with form (incompatible with ContextMixin) or without (incompatible with WizardView).
-
As a consequence of the above, it is basically impossible to write a type stub for WizardView.get_context_data(). This is a blocker for adding typings to Typeshed or directly to Formtools.
Proposed solution
Change the signature of WizardView.get_context_data() to:
def get_context_data(self, *, form=None, **kwargs)
That is, make form an optional keyword-only parameter. This is compatible with the plain **kwargs defined in ContextMixin because it allows form not to be passed, and because both versions don't accept any positional arguments.
For convenience, a get_context_data_for_step(self, form, **kwargs) method could be provided, which would called by get_context_data() either with the received form or self.get_form() (same logic as currently in render()):
def get_context_data(self, *, form=None, **kwargs):
form = form or self.get_form() # moved here from render()
context = super().get_context_data(form=form, **kwargs)
context.update(self.get_context_data_for_step(form, **kwargs))
...
def get_context_data_for_step(self, *, form, **kwargs):
return {} # default implementation
Summary
WizardViewdefinesget_context_data()with the following signature:However, in its superclass
TemplateView(or, specifically,ContextMixin) it has the following signature:This means that the override in
WizardViewis incompatible because it breaks the Liskov substitution principle:formis required byWizardView, but not byTemplateView.Why it matters
Code designed to work with any
TemplateView(such as a mixin that overridesget_context_data()to add an additional entry) may not work withWizardView.When the user overrides
get_context_data()in aWizardView, type checkers like Ty complain about the override being incompatible, no matter whether you define it withform(incompatible withContextMixin) or without (incompatible withWizardView).As a consequence of the above, it is basically impossible to write a type stub for
WizardView.get_context_data(). This is a blocker for adding typings to Typeshed or directly to Formtools.Proposed solution
Change the signature of
WizardView.get_context_data()to:That is, make
forman optional keyword-only parameter. This is compatible with the plain**kwargsdefined inContextMixinbecause it allowsformnot to be passed, and because both versions don't accept any positional arguments.For convenience, a
get_context_data_for_step(self, form, **kwargs)method could be provided, which would called byget_context_data()either with the receivedformorself.get_form()(same logic as currently inrender()):