Opened 20 months ago

Last modified 11 months ago

#26369 assigned New feature

Allow override of hardcoded defaults in model Field.formfield()

Reported by: James Pic Owned by: James Pic
Component: Database layer (models, ORM) Version: 1.9
Severity: Normal Keywords:
Cc: James Pic, hv@…, Kevin Brown Triage Stage: Someday/Maybe
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description (last modified by James Pic)

Currently, the model field builds the default form field that's used
by the modelform metaclass in Field.formfield(). It uses hardcoded defaults which it would be nice to be able to override with attributes.

Example patch: https://github.com/jpic/django/commit/d102f362f3c1ceaf2d5224d71f788c0821a481ae

This patch allows to use Radio widget by default for a OneToOne field:

    class TestModel(models.Model):
        name = models.CharField(max_length=200)

        test = models.OneToOneField(
            'self',
            null=True,
            blank=True,
            related_name='related_test_models',
            # This seems like it would always be useful
            formfield_defaults={
                'widget': forms.RadioSelect
            }
        )

Change History (9)

comment:1 Changed 20 months ago by James Pic

Description: modified (diff)

comment:2 Changed 20 months ago by James Pic

Cc: James Pic added

comment:3 Changed 20 months ago by Tim Graham

Component: FormsDatabase layer (models, ORM)
Type: Cleanup/optimizationNew feature

I'm not sure whether or not to accept this, so I raised it on the django-developers mailing list.

comment:4 Changed 20 months ago by Tim Graham

Triage Stage: UnreviewedSomeday/Maybe

comment:5 Changed 20 months ago by Thomas Güttler

Cc: hv@… added

comment:6 Changed 20 months ago by Thomas Güttler

I guess I understood what you want.

I see this problem: A django projects is a container for N apps.

Since there are N apps, and not just one: Who is allowed to provide defaults?

Yes, we already do change the default widgets. We use monkey patching: We modify the django classes. That is not a nice way, but works.

Yes, I would like to have an official solution, too.

comment:7 Changed 20 months ago by Kevin Brown

Cc: Kevin Brown added

comment:8 Changed 11 months ago by James Pic

Has patch: set
Owner: changed from nobody to James Pic
Patch needs improvement: set
Status: newassigned

comment:9 Changed 11 months ago by James Pic

I'm unsure if I wouldn't prefer to just be able to define a project-level default formfield callback, because that's going to depend on what the INSTALLED_APPS provide. Then for example, to make all relations to Foo a particular widget instead of Select, and to make all CharFields have a text field:

# settings.py:
DEFAULT_FORMFIELD='project.forms.project_formfield'

# project/forms.py
def project_formfield(db_field, form_class, defaults):
    if db_field.rel.to == Foo:
        defaults['widget'] = forms.RadioSelect
        
    if db_field.model == Foo and isinstance(db_field, models.CharField):
        defaults['widget'] = forms.Textarea

    return form_class(**defaults)

This seems even more powerful, I've updated the PR to match this.

Last edited 11 months ago by James Pic (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top