MultipleChoiceField empties incorrectly on a partial update using multipart/form-data · Issue #2894 · encode/django-rest-framework (original) (raw)

The root of this issue is that using multipart/form-data with a PATCH (partial=True on the serializer) there's no way to distinguish between "I am not including data for this MCF" vs "please empty this MCF", because they both look the same (zero occurrences of that key in the data).

The current implementation of MultipleChoiceField in DRF always assumes the latter, which is the more dangerous choice, since it leads to data loss. The cause of this is that MultipleChoiceField.get_value() calls QueryDict.getlist if the data is a QueryDict, and QueryDict.getlist() returns [] if the key does not occur in the QueryDict at all.

I think that for safety it would be better if MultipleChoiceField returned empty in case of no key found, rather than returning []. It could do this only if the root serializer has partial=True, so that in case of PUT emptying the field still works correctly.

The implication would be that there would be no way to empty a MultipleChoiceField via PATCH when using multipart/form-data, but I think that's better than always emptying a MultipleChoiceField when the intention was to not include it in the PATCH.