Shouldn't custom fields in ModelForms pick up model Field options by default?

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Shouldn't custom fields in ModelForms pick up model Field options by default?

Kevin Christopher Henry

Take a simple Model and ModelForm like this:

class Author(models.Model):
    name = models.CharField(max_length=80, blank=True, default="Joe",
help_text="A name")

class AuthorForm(forms.ModelForm):

    class Meta:
        model = Author

The resulting form will reflect the desired help text, default, and
blank options.

But if you decide to customize the widget, for example:

class AuthorForm(forms.ModelForm):
    name = forms.CharField(widget=forms.TextInput(attrs={'size':80}))

    class Meta:
        model = Author

the form field no longer reflects these model field options (that is,
there is no help text, no default value, and you can't save it blank).

This seems like undesirable behavior. At the very least it's
surprising, and should probably be documented here:
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-field-types.

I'm fairly new to Django, so unfortunately I'm not sure of the right
way to do this. One workaround is to set the fields manually, like:

    name = forms.CharField(widget=forms.TextInput(attrs={'size':80}),
required=False, initial="Joe", help_text="A name")

but that's an obvious violation of DRY. Another workaround, which
takes advantage of the fact that the options are getting properly set
in the call to the model field's formfield() method, is this:

    name = Author._meta.get_field("name").formfield
(form_class=forms.CharField, widget=forms.TextInput(attrs={'size':
80}))

but that's not ideal either, for obvious reasons.

Any thoughts?

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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Malcolm Tredinnick

On Wed, 2009-08-12 at 20:05 -0700, Kevin Henry wrote:
[...]

> But if you decide to customize the widget, for example:
>
> class AuthorForm(forms.ModelForm):
>     name = forms.CharField(widget=forms.TextInput(attrs={'size':80}))
>
>     class Meta:
>         model = Author
>
> the form field no longer reflects these model field options (that is,
> there is no help text, no default value, and you can't save it blank).

Correct. You told Django that you wanted to specify the field yourself
and it believed you. Django cannot know which attributes you intended to
leave out and which you wanted inherited, so it does the only possible
thing and leaves things entirely in your control.

>
> This seems like undesirable behavior. At the very least it's
> surprising,

Well, surprise is in the eye of the participant. As noted above, it
would be surprising to a lot of us if it did pick up the attributes
because it removes control from the user. The current behaviour isn't
illogical.

>  and should probably be documented here:
> http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-field-types.

Definitely. Please open a ticket (if one doesn't already exist in the
documentation component for this) and feel free to attach a patch with
some suggested wording.

>
> I'm fairly new to Django, so unfortunately I'm not sure of the right
> way to do this.

If all you want to do is change the widget, you can do that in the
form's __init__ method by updating self.fields["name"].widget, for
example.

Regards,
Malcolm



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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Kevin Christopher Henry

> Well, surprise is in the eye of the participant. As noted above, it
> would be surprising to a lot of us if it did pick up the attributes
> because it removes control from the user. The current behaviour isn't
> illogical.

Oh, I wasn't suggesting that the user shouldn't be able to override
those values, I was only talking about what the default behavior
should be if the user doesn't specify anything. If the user
instantiates a form field, and doesn't specify what 'required' should
be (and the field itself doesn't set this value), it just seems far
more natural to pick up the value the user already specified in the
model, rather than arbitrarily choosing 'True'.

Part of the reason I think this represents a common use case is that
these attributes seem fairly orthogonal to the purposes of validating/
rendering that fields and widgets are used for. That is, I wouldn't
imagine that it's common that your choice of which field or widget to
use to represent a model field will affect whether or not that field
is required, say. Of course, my experience is limited.

I don't know enough yet to suggest how this would be implemented, I
just wanted to throw the idea out there. But unless there's a
groundswell of support for my position, I guess I'll just file a
documentation ticket.

Cheers,
Kevin

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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Brian Rosner


On Aug 13, 2009, at 1:59 PM, Kevin Henry wrote:

>
>> Well, surprise is in the eye of the participant. As noted above, it
>> would be surprising to a lot of us if it did pick up the attributes
>> because it removes control from the user. The current behaviour isn't
>> illogical.
>
> Oh, I wasn't suggesting that the user shouldn't be able to override
> those values, I was only talking about what the default behavior
> should be if the user doesn't specify anything. If the user
> instantiates a form field, and doesn't specify what 'required' should
> be (and the field itself doesn't set this value), it just seems far
> more natural to pick up the value the user already specified in the
> model, rather than arbitrarily choosing 'True'.

It isn't choosing arbitrary defaults. When you declare a form field  
declaratively in your ModelForm we have to assume you want that field  
and everything that comes with it. So, behind the scenes the declared  
form field simply overrides what is the field for that particular  
field. Therefore the value it uses in-place of the model form field is  
the default value for that attribute of that form field you've just  
declared as being the replacement.

>
> Part of the reason I think this represents a common use case is that
> these attributes seem fairly orthogonal to the purposes of validating/
> rendering that fields and widgets are used for. That is, I wouldn't
> imagine that it's common that your choice of which field or widget to
> use to represent a model field will affect whether or not that field
> is required, say. Of course, my experience is limited.

I won't argue that you are wrong here, but to accomplish what you have  
asked for is going to involve more trickery than it is really worth  
(plus being backwards incompatible at this point). There has been  
mention of providing a simpler way to overriding widgets for a field  
(as that is the common case) without affecting the field. That  
particular proposal will go further than what you've brought up.

>
> I don't know enough yet to suggest how this would be implemented, I
> just wanted to throw the idea out there. But unless there's a
> groundswell of support for my position, I guess I'll just file a
> documentation ticket.

No doubt the documentation needs to be revised slightly for this. It  
is mentioned, but only as a single sentence that almost makes no  
sense ;-)

Please file a ticket for the documentation fix it would be greatly  
appreciated. :-)

Brian Rosner
http://oebfare.com


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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

dc-10
In reply to this post by Kevin Christopher Henry

If you want inherit default attributes from model just use

    name = Author._meta.get_field('name').formfield()


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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Ivan Sagalaev
In reply to this post by Malcolm Tredinnick

Malcolm Tredinnick wrote:
> If all you want to do is change the widget, you can do that in the
> form's __init__ method by updating self.fields["name"].widget, for
> example.

There's also a ticket waiting for check-in implementing this common
usecase: http://code.djangoproject.com/ticket/9223

P.S. Sorry for the shameless plug :-)

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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Kevin Christopher Henry

In terms of backward compatibility, perhaps there could be a new
keyword argument to Field, something like with_model_defaults, that
the user would use to indicate a desire to get the attributes from the
Model. How would this work? Maybe something like this (this is just a
sketch): Field.__init__() works the same way, except that it also
stores the value of the keyword arguments (with_model_defaults, as
well as the others, since the user should be able to override
individual settings). Then ModelForm's metaclass will call a method on
the field, passing in the field name. The field can then extract the
default values from the Model and set itself up appropriately.

Too much trickery? Before looking into how Django works I would have
definitely said yes, but now my standards have changed. :) (That's not
a criticism, I'm very happy with the trickery Django implies to make
life easier for the user.)


> There's also a ticket waiting for check-in implementing this common
> usecase:http://code.djangoproject.com/ticket/9223

Thanks, the accompanying discussion is very interesting and on point.
But as someone there points out, why stop at widgets? The discussion
strengthens my intuition that widgets, fields, and the attributes I'm
discussing here are fairly orthogonal concepts, and the current all-or-
nothing declarative syntax couples them too tightly. Both your
solution and the (much less thought-out) one I just proposed feel too
small to me, but I'm not sure of a better solution.

Cheers,
Kevin

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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Kevin Christopher Henry
In reply to this post by Brian Rosner

> Please file a ticket for the documentation fix it would be greatly  
> appreciated. :-)

Will do.

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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Ivan Sagalaev
In reply to this post by Kevin Christopher Henry

Kevin Henry wrote:
>> There's also a ticket waiting for check-in implementing this common
>> usecase:http://code.djangoproject.com/ticket/9223
>
> Thanks, the accompanying discussion is very interesting and on point.
> But as someone there points out, why stop at widgets?

Because customizing widgets is a common request, unlike other attributes.

I believe that the consistency you're talking about is not very useful
here. Speaking from my experience overwriting anything other than a
widget is needed rarely and is easily accomplished with a custom 2-line
helper function.

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

Reply | Threaded
Open this post in threaded view
|

Re: Shouldn't custom fields in ModelForms pick up model Field options by default?

Kevin Christopher Henry

> > Thanks, the accompanying discussion is very interesting and on point.
> > But as someone there points out, why stop at widgets?
>
> Because customizing widgets is a common request, unlike other attributes.

But customizing fields is quite common, no? I agree that it's rare
that you will want to override required, help_text, etc.—in fact,
that's exactly my point. The current syntax forces you to do so when
customizing the form just to get back to the behavior already
specified in the model. Your solution solves this problem for the
common case of customizing the widget, but the issue is just as
applicable for the common case of customizing the field.

But at this point, I'll come up with a more concrete proposal before
carrying on.

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