When building a Django application, we were exposed to (forms) MultiValueField
and MultiWidget
.
They seem like an interesting approach to compose their respective base classes, giving more modularity.
Yet, now it seems to us that the actual piece that would make those two shine bright would be a db.models.MultiField
. Here is the reasoning:
It seems that, when using a ModelForm, Django is enforcing a strict 1-to-1 association between a models.Field and a forms.Field. Now, with
forms.MultiValueField
, despite this strict 1-to-1 association, you can have a singlemodels.Field
actually associated to the numerousforms.Field
composing theforms.MultiValueField
.Yet, it is limited to the case where a single
models.Field
maps more naturally to severalforms.Field
. What seems very interesting would be the ability to associate any number ofmodels.Fields
to any number offorms.Field
. The only piece that seems to be missing to get there is an hypotheticalmodels.MultiField
. It could communicate with the exterior through acompress()
method (see.MultiValueField
), and potentially adecompress()
method in the other direction (seeMultiWidget
).
The questions would then be (assuming this requirement is not emerging from a misunderstanding of Django): Is there a way to compose modelds.Field
in Django ? If not, why is such an empowering concept not implemented in this great framework ;) ?
EDIT: To give a motivating example, imagine we want to implement a partial date (a date that can be precise to a day, or just precise to a month and a year, or alternatively just a year), with a Model
following the one presented in this answer, i.e.:
- a
DateField
, representing the date - a
CharField
, to indicate whether the date is complete or month + year or just year.
This model is working just fine with the default ModelForm
, but now we want to introduce some consistency check: if a date is only precise to the month (month + year or just year), its day part should be 1, and if it is only precise to the year, its month part should also be 1.
This is a cross-fields check (two different Field
s from the ModelForm
needs to be accessed to complete it), so it has to be implemented at the Form.clean()
level. This check would need to be copy-pasted in each form containing a partial date, which goes against the DRY cherished by Django.
Now let's imagine Django is providing this hypothetical models.MultiField
, which would be a composite models.Field
. We could define a PartialDate
class deriving from MultiField
and containing the two leaf fields defined above (DateField
and CharField
). We could now say that the form field corresponding to this single model field (in a ModelForm
) is a class derived from forms.MultiValueField
. This class could implement the consistency check above, at the field level: it is not a cross-field check anymore.
This way, we got rid of the code duplication: any model could use a PartialDate
field, automatically making any ModelForm
s mapping to it use the forms.MultiValueField
implementing the consistency check, whose code was only written in one place.
(This is a simple example, it is easy to imagine it can get way more complex in production code, with consistency check you do not want to copy paste)