django-rest-framework
django-rest-framework copied to clipboard
Clearing a ManyToManyField in a multipart PATCH Request
Hello,
I'm having some trouble clearing a ManyToMany
field in a multipart PATCH request.
In a JSON request, I would clear my ManyToMany
field, 'many_to_many_field'
by PATCHing something like:
{"many_to_many_field": []}
However, in a multipart PATCH request, sending values including '[]'
, ''
, 'null'
, 'None'
, etc all yield the following error:
["Incorrect type. Expected pk value, received unicode."]
It seems that ManyRelatedField.get_value()
does not recognize any of those options as special indicators of empty
.
I think the crux of this boils down to the fact that there's no way to encode []
in multipart?
from rest_framework.test import APIClient
client = APIClient()
client._encode_data({'foo':[1, 2, 3]}, format='multipart')
('--BoUnDaRyStRiNg\r\nContent-Disposition: form-data; name="foo"\r\n\r\n1\r\n--BoUnDaRyStRiNg\r\nContent-Disposition: form-data; name="foo"\r\n\r\n2\r\n--BoUnDaRyStRiNg--\r\n', u'multipart/form-data; boundary=BoUnDaRyStRiNg; charset=utf-8')
client._encode_data({'foo': []}, format='multipart')
('--BoUnDaRyStRiNg--\r\n', u'multipart/form-data; boundary=BoUnDaRyStRiNg; charset=utf-8')
I think the crux of this boils down to the fact that there's no way to encode [] in multipart?
Correct. This is a constraint of HTML form input. We can either document this, or instead simply not display (or disable with a tooltip) the PATCH button for form input, and only enable it for raw JSON input.
See also #2894
My workaround is listed below. Hope we will have a nice solution later.
Using null when firing an ajax request.
if (subscribersList.select2('data').length === 0) {
data.push({"name": "subscribers", "value": null})
}
Add some code to clear ManyToManyField in is_valid method
def is_valid(self, raise_exception=False):
data = self.get_initial()
if data.get('subscribers')[0] == '':
self.instance.subscribers.clear()
del self.fields['subscribers']
return super().is_valid(raise_exception)
This comment from 2017 just saved my sanity.
Would it be something to consider, making this a supported solution?
I.e. We allow "None"
with allow_null=True
, so why not allow "[]"
or "None"
in a ManyToMany html submit?
I am open to review an implementation which can implement it properly without any side effect
This comment from 2017 just saved my sanity. Would it be something to consider, making this a supported solution? I.e. We allow
"None"
withallow_null=True
, so why not allow"[]"
or"None"
in a ManyToMany html submit?
I have totally no idea for what I was doing at that moment. :) It's glad to see the snippet can help you a little bit. Nowadays, I am just using Starlette + Vue (and Naive UI) if I need to create some demos.