Opened 15 years ago
Closed 9 years ago
#12915 closed Bug (duplicate)
formfield_callback is lost in an inherited ModelForm
Reported by: | Ilya Semenov | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 1.1 |
Severity: | Normal | Keywords: | |
Cc: | tom@…, vlastimil.zima@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | yes |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
Consider the following code:
class BaseTicketForm(forms.ModelForm): class Meta: fields = (...) formfield_callback = lambda f: .... class AddTicketForm(BaseTicketForm): pass class EditTicketForm(BaseTicketForm): # some logic related to editing tickets here
When an instance of AddTicketForm or EditTicketForm is created, a user would expect that formfield_callback is applied. However, the current implementation doesn't do that; instead, a user is forced to copy-paste formfield_callback to each and every derived class.
Attachments (2)
Change History (20)
comment:1 by , 15 years ago
comment:2 by , 15 years ago
No, changing pop() to get() doesn't help. That does store a manually specified formfield_callback for a class; but that doesn't lookup a missing formfield_callback from a parent. Moreover, it will break on a double inheritance chain, e.g. when class A(ModelForm) stores a formfield_classback, class B(A) doesn't store but still can lookup parent, then class C(B) can't even lookup since B didn't store formfield_callback.
I am attaching a patch which adds the desired behavior accurately. Please let me know if it's of any interest to commiters and I will come up with a regression test.
by , 15 years ago
Attachment: | formfield_callback_inheritance.diff added |
---|
comment:3 by , 15 years ago
Has patch: | set |
---|---|
Needs tests: | set |
comment:4 by , 15 years ago
A little note for those who don't understand the importance of the problem. I truly believe that an empty inherited class should always behave exactly as its parent. That is a fundamental principle of polymorphism, which is not followed by ModelForms.
by , 15 years ago
Attachment: | formfield_callback_inheritance_v2.diff added |
---|
a simplier version which leaves the inheritance/lookup logic to Python
comment:5 by , 15 years ago
Patch needs improvement: | set |
---|---|
Triage Stage: | Unreviewed → Accepted |
I'm not completely happy with either of the patches you present, but I accept the problem.
comment:6 by , 14 years ago
Type: | → Bug |
---|
comment:7 by , 14 years ago
Severity: | → Normal |
---|
comment:8 by , 14 years ago
Cc: | added |
---|---|
Easy pickings: | unset |
comment:10 by , 13 years ago
Needs documentation: | set |
---|
comment:11 by , 11 years ago
Also, just FTR - formfield_callback use *is* documented with modelform_factory.
comment:12 by , 10 years ago
How'd you like to improve the latest patch? It's been 5 years, and I'm suffering from this again.
follow-up: 16 comment:14 by , 10 years ago
Added tests: https://github.com/IlyaSemenov/django/tree/ticket_12915
I am not happy with the patch either, but the main problem here is the original design decision to provide formfield_callback as a class-level lambda rather than @staticmethod or a Meta class attribute.
Will it make it better if I come up with a patch which moves formfield_callback
into the Meta class (where it would make perfect sense along with widgets
and labels
), or even allows to use either way (for backward compatibility)?
comment:15 by , 10 years ago
Needs tests: | unset |
---|
comment:16 by , 10 years ago
Replying to IlyaSemenov:
Will it make it better if I come up with a patch which moves
formfield_callback
into the Meta class (where it would make perfect sense along withwidgets
andlabels
), or even allows to use either way (for backward compatibility)?
Indeed, I think it would be an interesting alternative to consider.
comment:17 by , 9 years ago
Cc: | added |
---|
comment:18 by , 9 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Duplicate of #24974 which is fixed in Django 1.10.
I'd say the fact that the value of
formfield_callback
is stored as a ModelForm class attribute is an internal implementation detail and that's why it isn't documented as such.Anyway, maybe changing the
pop()
toget()
here does it?: http://code.djangoproject.com/browser/django/trunk/django/forms/models.py?rev=12402#L204