Opened 3 years ago

Closed 2 months ago

Last modified 2 months ago

#18166 closed New feature (fixed)

Allow the formset class to contribute kwargs to form instances

Reported by: tevans Owned by: sergei-maertens
Component: Forms Version: master
Severity: Normal Keywords: forms formset kwargs
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by lrekucki)

When we use a formset, each form is instantiated by the method BaseFormSet._construct_forms(), which is called from BaseFormSet.__init__()

_construct_forms() allows for additional kwargs to be passed through to the individual form constructor, but BaseFormSet.__init__() does not provide any mechanism for kwargs to be passed through to the _construct_forms() call.

Also, we may not be able to supply a static unchanging list of kwargs that should be supplied to each form constructor - the kwargs we want to pass may depend upon the specific instance of the form being instantiated.

I propose the following changes:

Add a form_kwargs argument to BaseFormSet.__init__(). This would be stored on self, and consumed in BaseFormSet._construct_forms()

Add a method, BaseFormSet._kwargs_for_form(self, i). This method would be called for each form instantiated, passing the index of the form within the formset. The return value of this method would be merged with the form_kwargs supplied in BaseFormSet.__init__() and used to instantiate the form.

With these changes, a user could add additional constructor arguments to all forms by passing in form_kwargs to the formset constructor, and could add additional constructor arguments to specific forms by implementing _kwargs_for_form on a derived BaseFormSet class.

(I found it strange, when BaseFormSet was written, it was clearly intended to be able to pass kwargs to the forms - _construct_form() allows for it, there just is not the plumbing to do so. I worked around this by redefining - copy/pasting - the _construct_forms() method in my derived BaseFormSet class)

Patch doesn't have tests or doc changes, will add if this idea gets traction.

Cheers

Tom

Attachments (1)

django-formset-form-kwargs.diff (2.1 KB) - added by tevans 3 years ago.
Patch implementing features described in ticket

Download all attachments as: .zip

Change History (13)

Changed 3 years ago by tevans

Patch implementing features described in ticket

comment:1 follow-up: Changed 3 years ago by tevans

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Hmm, wiki markup that turns __init__ into init is less than useful for Python discussion :/

comment:2 Changed 3 years ago by tevans

  • Needs documentation set
  • Needs tests set

comment:3 in reply to: ↑ 1 Changed 3 years ago by lrekucki

  • Description modified (diff)

Replying to tevans:

Hmm, wiki markup that turns __init__ into init is less than useful for Python discussion :/

You can use formatting: {{{ __init__ }}} will show as __init__. There's both live preview and a preview button.

comment:4 follow-up: Changed 3 years ago by akaariai

Just as an idea: how about defining a new method:

def get_single_form(self, i, defaults):
    """
    Override me to have total control over the single forms.
    """
    return self.form(**defaults)

and use that instead of self.form() in the _construct_form() method. This would be more powerful and easier to implement.

comment:5 in reply to: ↑ 4 Changed 3 years ago by tevans

Replying to akaariai:

Just as an idea: how about defining a new method:

def get_single_form(self, i, defaults):
    """
    Override me to have total control over the single forms.
    """
    return self.form(**defaults)

and use that instead of self.form() in the _construct_form() method. This would be more powerful and easier to implement.

Yes, I like that. I would like to also keep the idea of being able to contribute to a form's kwargs without defining a BaseFormSet subclass, eg by passing them to BaseFormSet.__init__.

I should get some time this w/e to re-roll the patch.

comment:6 Changed 3 years ago by anonymous

  • Patch needs improvement set
  • Triage Stage changed from Unreviewed to Accepted

Agreed, a method for implementing this is a good idea, but please let's skip the redundant 'simple' prefix, just call it get_form.

comment:7 Changed 3 years ago by jezdez

Oops that was me.

comment:8 Changed 2 months ago by sergei-maertens

  • Owner changed from nobody to sergei-maertens
  • Status changed from new to assigned

comment:9 Changed 2 months ago by sergei-maertens

I'll have a go at this

comment:10 Changed 2 months ago by sergei-maertens

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:11 Changed 2 months ago by Sergei Maertens <sergei@…>

  • Resolution set to fixed
  • Status changed from assigned to closed

In 238e2ac3:

Fixed #18166 -- Added form_kwargs support to formsets.

By specifying form_kwargs when instantiating the formset, or overriding
the get_form_kwargs method on a formset class, you can pass extra
keyword arguments to the underlying Form instances.

Includes tests and documentation update.

comment:12 Changed 2 months ago by Russell Keith-Magee <russell@…>

In fe21fb81:

Merge pull request #4757 from sergei-maertens/ticket_18166

Fixed #18166 -- Added ability to pass kwargs to the form constructor in a formset.

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