Code

Opened 7 years ago

Closed 7 years ago

#6162 closed (fixed)

ModelForm.__init__() should match argument signature of "standard" forms

Reported by: ubernostrum Owned by: nobody
Component: Forms Version: master
Severity: Keywords: modelform
Cc: Triage Stage: Design decision needed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Currently, ModelForm.__init__() differs from the __init__() of a "standard" newforms form in two ways:

  1. It requires an instance of the model to be passed in, and cannot fall back to a default.
  2. It requires this to be the first positional argument, while on "standard" forms the first positional argument is data.

A number of use cases -- particularly generic form-handling code -- would be made much simpler if instead instance was optional (with ModelForm falling back to creating an instance based on _meta.model if it's not supplied), and if it was moved further back in the list of arguments so as to allow code to work with the standard argument signature of BaseForm.__init__() as much as possible.

Attachments (2)

modelform-init.diff (13.2 KB) - added by ubernostrum 7 years ago.
Patch which "fixes" ModelForm.__init__()
modelform-init-2.diff (17.2 KB) - added by ubernostrum 7 years ago.
Updated patch

Download all attachments as: .zip

Change History (5)

Changed 7 years ago by ubernostrum

Patch which "fixes" ModelForm.__init__()

Changed 7 years ago by ubernostrum

Updated patch

comment:1 follow-up: Changed 7 years ago by ubernostrum

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Design decision needed

New patch ensures that a ModelForm without a model or instance throws an error, and tests and documents the now-possible case of a ModelForm working with any of multiple models at runtime.

Discussion for anyone who's only watching here is taking place on django-dev.

comment:2 in reply to: ↑ 1 Changed 7 years ago by bear330

I think the below code block which is for form.save method in meta class should be changed.

        # Don't allow more than one Meta model defenition in bases. The fields
        # would be generated correctly, but the save method won't deal with
        # more than one object.
        base_models = []
        for base in bases:
            base_opts = getattr(base, '_meta', None)
            base_model = getattr(base_opts, 'model', None)
            if base_model is not None:
                base_models.append(base_model)
        if len(base_models) > 1:
            raise ImproperlyConfigured("%s's base classes define more than one model." % name)

        # If a model is defined, extract form fields from it and add them to base_fields
        if attrs['_meta'].model is not None:
            # Don't allow a subclass to define a Meta model if a parent class has.
            # Technically the right fields would be generated, but the save 
            # method will not deal with more than one model.
            for base in bases:
                base_opts = getattr(base, '_meta', None)
                base_model = getattr(base_opts, 'model', None)
                if base_model is not None:
                    raise ImproperlyConfigured('%s defines more than one model.' % name)
            model_fields = fields_for_model(opts.model, opts.fields, opts.exclude)
            # fields declared in base classes override fields from the model
            model_fields.update(declared_fields)
            attrs['base_fields'] = model_fields
        else:
            attrs['base_fields'] = declared_fields
        return type.__new__(cls, name, bases, attrs)

(Maybe I should send a patch here, but I am not familiar to patch tool. I will learn it soon...)

Remove those checks, will make mulitiple inherit from ModelForm possible.

Thanks.

comment:3 Changed 7 years ago by jkocherhans

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

(In [6915]) Fixed #6162. ModelForm's init signature now matches Form's. This is a backwards incompatbile change. Based largely on a patch by ubernostrum.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.