Difference between inheritance and function
Closed this issue · 3 comments
Hello,
djangorestframework-dataclasses is helping me document my API with drf-spectacular.
Thanks for that.
I noticed a inherited dataclass serializer is different than one created by a function.
An example:
@dataclass
class Monty:
python: bool
MontySerializer = DataclassSerializer(dataclass=Monty)
class MontyClassSerializer(DataclassSerializer):
class Meta:
dataclass = Monty
monty = Monty(True)
MontyClassSerializer(instance = monty) # works
MontySerializer(instance=monty) # TypeError: 'DataclassSerializer' object is not callable
My expectation is that both, class and function would have the same result.
It really doubles my code when it needs to be created as an actual class.
Is there a way around this?
There is no function: what you're doing is calling the constructor of the DataclassSerializer
class, which returns a DataclassSerializer
instance, not a type. It's meant to be used as substitution for the explicit type in places where you'd instantiate the serializer, not to create a serializer type. E.g. like this:
ser = DataclassSerializer(dataclass=Monty, instance=monty)
# use in place of:
ser = MontyClassSerializer(instance=monty)
Hi, Thank you for the reply. My expectations and what actually happens under the hood were mismatched.
I do think there's value in using the syntax DataclassSerializer(dataclass=Monty)
to return a class.
Especially when the use case is documenting the REST API for @api_view
functions.
ps. Changed the code example in the top post. MontyClassSerializer now properly inherits from DataclassSerializer.
I do think there's value in using the syntax
DataclassSerializer(dataclass=Monty)
to return a class.
I'm afraid that's not possible, both because that syntax already has another function, and because technically it's somewhere between very complicated and impossible to implement.
If you really want to create serializers programatically, you can do that with type()
:
MontySerializer = type('MontySerializer', (DataclassSerializer, ), {'Meta': type('Meta', (), {'dataclass': Monty}})
though you should probably wrap it in another function to keep things readable.