I can't get DRF to allow providing a read_only version of nested data and a writeable version of just the ids in a list in one serializer. It feels like a bug to me, but usually that just means I'm not understanding the framework well enough, and being misled by the error message.
class Individual(models.Model):
household = models.ForeignKey(
'household.Household',
null=True,
related_name="individuals")
name = models.CharField(
max_length=100, default='')
class Household(models.Model):
address_line1 = models.CharField(max_length=64, default='')
class IndividualListSerializer(serializers.ModelSerializer):
class Meta:
model = Individual
depth = 0
fields = ('url', 'id', 'name', 'household')
read_only_fields = fields
class HouseholdUpdateSerializer(serializers.ModelSerializer):
individuals_details = IndividualListSerializer(many=True, source='individuals', read_only=True)
class Meta:
model = Household
fields = ('id', 'address_line1', 'individuals', 'individuals_details')
read_only_fields = ('id', 'individuals_details')
The error comes back as
AssertionError: The `.update()` method does not support writable nested fields by default. Write an explicit `.update()` method for serializer `household.serializers.HouseholdUpdateSerializer`, or set `read_only=True` on nested serializer fields. // Werkzeug Debugger</title>
I have used read_only on the nested field (which is needed in the response to the update). Yet the error still indicates I am not doing so.
If I remove the individuals
field entirely, the individuals_details
returns the readable data without the error, but since it's ignoring the individuals
data being sent, it isn't updating that list.
If I remove the individuals_details
field, DRF accepts the individuals
list and performs the update on the model. But then the return data needed is not there.
So, while either the read nested or write list work on their own, when the other is added the serializer doesn't function.
This seems a pretty common area people get stuck, and it seems the answers this SO question have become the best practice for a pattern. But it doesn't work in my code for some reason. Perhaps because of the ManyToOne in my models.
I can probably work around this by changing the client to perform the PUT for the update, ignore the response, and then do a separate GET, but that's sloppy and shouldn't be needed if the DRF update can be made to work as expected.
What am I missing in this?