Opened 16 years ago

Closed 16 years ago

#6162 closed (fixed)

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

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

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 James Bennett 16 years ago.
Patch which "fixes" ModelForm.__init__()
modelform-init-2.diff (17.2 KB ) - added by James Bennett 16 years ago.
Updated patch

Download all attachments as: .zip

Change History (5)

by James Bennett, 16 years ago

Attachment: modelform-init.diff added

Patch which "fixes" ModelForm.__init__()

by James Bennett, 16 years ago

Attachment: modelform-init-2.diff added

Updated patch

comment:1 by James Bennett, 16 years ago

Triage Stage: UnreviewedDesign 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.

in reply to:  1 comment:2 by bear330, 16 years ago

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 by jkocherhans, 16 years ago

Resolution: fixed
Status: newclosed

(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.

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