django-rest-framework icon indicating copy to clipboard operation
django-rest-framework copied to clipboard

`default` value for field gets deepcopied causing sentinels to get copied

Open txomon opened this issue 2 years ago • 1 comments

Hello,

I have found that the use of sentinel values such as object() fails with the current implementation of serializers.

My usecase is when I want to distinguish between the user not providing a value and not providing the attribute at all. Example:

NO_ATTR = object()

class MySerializer:
    my_field = serializers.UUIDField(default=NO_ATTR, allow_null=True)

Any object deserialized by MySerializer, whenever my_field is not sent, will result in a random object() being generated, and therefore is comparison not being able to be used.

I have narrowed it down to all the generator based _*_fields() properties that use copy.deepcopy() under the hood, and generate new instances for every deserialization.

It seems like a way to overcome this is through setting default=lambda: NO_ATTR, but that doesn't seem like a nice solution. I'm not sure on whether this is a well known limitation to developers, but I haven't been able to find any references. Would it make sense to at least document this limitation?

Checklist

  • [ ] Raised initially as discussion
  • [X] This cannot be dealt with as a third party library. (We prefer new functionality to be in the form of third party libraries where possible.)
  • [X] I have reduced the issue to the simplest possible case.

txomon avatar Oct 19 '23 14:10 txomon

I believe you can make use of rest_framework.fields.empty which is a sentinel value similar to what you're looking for. It also happens to be the default if no other one is specified.

kevin-brown avatar Oct 22 '23 03:10 kevin-brown