On Nov 8, 2007 1:26 PM, Joseph Kocherhans <[EMAIL PROTECTED]> wrote:
>
> form_for_model and form_for_instance seem like complicated and clever
> ways to accomplish what basically boils down to a form that has a save
> method and can accept a model instance in its constructor method.
> ModelForm would be a declarative class that requires, at minimum, a
> model attribute. Other attributes would include:
...
> - formfield_callback (a function that takes a db field and **kwargs
> and returns a form field or None)
> - fields (a list of field names to include in the form)
> - exclude (a list of field names to exclude from the form)

Regular readers will note that I've been an advocate for expanding the
capabilities of form_for_model/instance. This isn't because I believe
that the form_for_* syntax has any particular strengths, but because I
have a lot of use for dynamic form generation based on a model. I know
that it is possible to dynamically generate a form without using
form_for_* (by overriding fields lists in __init__, etc), but those
approaches aren't that elegant, IMHO - certainly not as elegant as
just specifying a list of fields that you want to include on a form.

I was under the impression that the form_for_* syntax was BDFL
blessed; as a result, I was concentrating on how to maximize the
utility of the blessed format. However, if an alternate class-based
syntax is an available option, I'm certainly +1 to persuing those
options.

The sort of syntax you are proposing has the potential to be much more
'legible' than cramming everything into arguments on a function
declaration, and has the potential to make the simple tasks (such as
adding a formfield callback, or a custom save method) much more
intuitive and pythonic.

If we're kicking around ideas on this, here's a slightly different
suggestion. First, an example:

class MyForm(Form):
    extra_field = forms.CharField()

    class Meta:
        model = MyModel
        fields = ('a','b')
        def formfield(f):
            return ...

    def save():
       ...

i.e., rather than writing a new ModelForm base class, put the
'form_for_*' stuff into a Meta class (Meta probably isn't the right
name, but it will do for now), which is used by the BaseForm metaclass
as a set of assembly instructions for how to add model/instance based
fields to MyForm.

If you provide a Meta class, any of the field/exclude declarations are
used to add new fields to the model; if there is a formfield() method
on the Meta class, it is used to determine which Field class will be
used.

The fields added from the Meta class augment those provided manually
(useful for the 'form_for_model plus these extra fields' use case,
such as is required for password validation). If you need custom
save/clean methods, you put them right in the form definition where
they are required, which is exactly what you would do if you were
manually defining the form from scratch.

> The biggest problem I see is that this would be entirely backwards
> incompatible with the way form_for_model and form_for_instance work
> now. (especially the latter) It *may* be possible to change form_for_X
> into some sort of hackish wrappers, but it wouldn't be pretty.

If we decide to go down this path, I would prefer to see the
form_for_* APIs deprecated and removed, rather than maintained as
wrappers. If a wrapper is trivial, there's no real harm in keeping it
around, but if its going to take a lot of effort to build and
maintain, we could end up with a bigger bug hole and image problem
than if we just grit our teeth and rip the band-aid off in one swift
action.

This obviously means preparing the path well - lots of prior warning
that the change will happen, maybe a release before the change comes
into effect, plus public commentary on _why_ we're making such a big
change, a mea culpa for getting it wrong in the first place, and good
documentation on how to manage the change. However, my gut reaction is
that one well managed large change will cause less drama than lots of
little bug fixes to an API wrapper.

Yours,
Russ Magee %-)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to