Hello, There was some discussion on the current limitations of the ModelForm API in the past couple of days on IRC, I'd like to make a proposal to address some of them.
I wrote django-floppyforms, a library that lets you render forms using templates instead of python code. It behaves exactly like the Django forms library, the only difference is the import path. Import `floppyforms as forms` and when you render a form, the HTML code comes from templates. There is still a limitation with ModelForms: since there is no way to globally override the model field -> form field/widget mapping since ModelForms fields come from the model definition. I documented this here: http://django-floppyforms.readthedocs.org/en/latest/differences.html#modelforms It is possible to override widgets using the Meta.widgets dict but not in a way that would switch all the ModelForm's fields to template-based widgets automatically. The idea is to have custom ModelForm subclasses with specific strategy on the model field -> form field mapping. This is currently possible using something called `formfield_callback` as a ModelForm class attribute: it is simply a callback that takes a db field and returns a form field. But this callback is a) private and b) limited: it gets lost in the inheritance chain as described in ticket #12915: https://code.djangoproject.com/ticket/12915 A discussion thread was started a couple of days ago for a design decision about formfield_callback: should we consider its behaviour as buggy or leave it as it is? In fact formfield_callback is only used by the admin, which has custom widgets for pretty much every db field. This customization is done using the following methods and attributes (all in django/contrib/admin/options.py): FORMFIELD_FOR_DBFIELD_DEFAULTS ModelAdmin.formfield_overrides ModelAdmin.formfield_for_dbfield(db_field, **kwargs) ModelAdmin.formfield_for_choicefield(db_field, **kwargs) ModelAdmin.formfield_for_foreignkey(db_field, **kwargs) ModelAdmin.formfield_for_manytomany(db_field, **kwargs) In most cases those methods end up calling formfield() on the DB field object, with some arguments for customizing the field class (wrongly called `form_class`) and its constructor arguments (widget, label, help_text, required, etc). The arguments to db_field.formfield() are passed via the formfield_callback function I mentioned earlier. My proposal is to move that field customization API from the ModelAdmin class back to ModelForm: * Move formfield_for_* to ModelForm and document them as public APIs * Deprecate `formfield_callback` * Write an AdminModelForm class that implements all the admin form fields and widgets customization * Modify ModelAdmin to make use of that base class * (maybe?) deprecate ModelForm.Meta.widgets in favor of something similar to the admin's formfield_overrides, which is more generic. I see the following advantages to this: * This would allow people to have "site-wide" fields/widgets overrides, which is a feature that the admin is already proving useful. Write a nice date picker once, register it for all your DateFields globally. * Maintainers of form libraries can ship a base ModelForm class that implements custom fields/widgets while keeping API compatibility with Django. Backwards-compatibility shouldn't be an issue as this touches only a couple of ModelAdmin methods. Regarding formfield_callback, despite it being a private API I'm not sure it can be removed safely. There are references to it on StackOverflow and on the Django bug tracker. I'm happy to work on a patch if core devs agree to accept this. Thoughts? Regards, Bruno -- You received this message because you are subscribed to the Google Groups "Django developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/django-developers?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
