3👍
While testing the models with the APIClient rest_framework.test.APIClient
and making a post request with more complex data and nested serializer, the format must be set explicitly to json
as such
def test_a_feature(self):
self.client = APIClient()
payload = {
"name": "A Foo",
"description": "A happy foo running in the woods of Central Park",
"bars": [
{name : "a"},
{name : "b"},
{name : "c"},
]
}
self.client.post(reverse('foo-list'), payload, format='json')
0👍
I think I have found a great solution to your issue in the docs
Writable nested serializers
By default nested serializers are read-only. If you want to support write-operations to a nested
serializer field you’ll need to create create() and/or update()
methods in order to explicitly specify how the child relationships
should be saved:
The docs continue to give an example of how you would implement this:
class TrackSerializer(serializers.ModelSerializer): class Meta: model = Track fields = ['order', 'title', 'duration'] class AlbumSerializer(serializers.ModelSerializer): tracks = TrackSerializer(many=True) class Meta: model = Album fields = ['album_name', 'artist', 'tracks'] def create(self, validated_data): tracks_data = validated_data.pop('tracks') album = Album.objects.create(**validated_data) for track_data in tracks_data: Track.objects.create(album=album, **track_data) return album >>> data = { 'album_name': 'The Grey Album', 'artist': 'Danger Mouse', 'tracks': [ {'order': 1, 'title': 'Public Service Announcement', 'duration': 245}, {'order': 2, 'title': 'What More Can I Say', 'duration': 264}, {'order': 3, 'title': 'Encore', 'duration': 159}, ], } >>> serializer = AlbumSerializer(data=data) >>> serializer.is_valid() True >>> serializer.save() <Album: Album object>
So in your case, you would define the FooSerializer
and the BarsSerializer
like this:
class BarsSerializer(serializers.ModelSerializer):
class Meta:
model = Bar
fields = ['name'] # Note that I have removed the 'foo' field since I have re-written your create method in the FooSerializer.
class FooSerializer(serializers.ModelSerializer):
bars = BarsSerializer(many=True)
class Meta:
model = Foo
fields = ['id', 'author', 'name', 'description', 'bars']
def create(self, validated_data):
validated_data['author'] = self.context['request'].user
bars_data = validated_data.pop('bars') # Validated data is your dict with the 'bars' list nested inside it
Foo = Foo.objects.create(**validated_data) # Foo object manager is tested and works
# Now we just iterate over the bars list...
for bar_data in bars_data:
#... and create a bar for each bar_data
Bar.objects.create(foo=foo, **bar_data)
return Foo
I haven’t tested this code and it may not work, but it is taken right from the docs.
- [Django]-Django Markdown Editor does not show up
- [Django]-Integrating Dagster with Django
- [Django]-IntegrityError at /***/ (1048, "Column '***' cannot be null") in python django
- [Django]-Django queryset of reverse manytomany relation
- [Django]-Get ID of Django record after it has been created in a ModelViewSet