Is there a model MultiField (any way to compose db

2019-02-20 02:40发布

问题:

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 single models.Field actually associated to the numerous forms.Field composing the forms.MultiValueField.

  • Yet, it is limited to the case where a single models.Field maps more naturally to several forms.Field. What seems very interesting would be the ability to associate any number of models.Fields to any number of forms.Field. The only piece that seems to be missing to get there is an hypothetical models.MultiField. It could communicate with the exterior through a compress() method (see. MultiValueField), and potentially a decompress() method in the other direction (see MultiWidget).

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 Fields 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 PartialDateclass 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 ModelForms 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)

回答1:

Possible: Yes. You could either subclass djangos model class, or monkey-patch that class into the existing model module.

Just (educated) guessing: I think it is not missing, but not needed.

In DB-Applications, combined fields will almost always come with special business rules. So you will have to implement a different display and validation for each one of them anyway.

Which you already can easily do in the models.Form.

Maybe you should look at customization of models.Form?