Reputation: 2009
I'm really struggling with sending my data with postman in correct form to my Django backend. I followed the approach in the Django documentation for a writeable nested Seralizer and adapted it to my case. If I pass the data to my serializer via the shell, everything works and I can create the two object instances Story
and File
. But if I try to do the same with post man, it is not successful and receive the following error Message: Got AttributeError when attempting to get a value for field 'file' on serializer 'StoryCreateUpdateSerializer'. The serializer field might be named incorrectly and not match any attribute or key on the 'Story' instance. Original exception text was: 'Story' object has no attribute 'file'.
Successfull Request via Shell:
>>> data = {
'title': 'HALLLO',
'file': [
{'content': 'Public Service Announcement'},
{'content': 'Public Service Announcement'},
{'content': 'Public Service Announcement'},
],
}
>>> serializer = StoryCreateUpdateSerializer(data=data)
>>> serializer.is_valid()
True
>>> serializer.save()
Not Successfull Request via Postman. Header: Content-Type: application/json. Body: Raw
{
"title": "Test",
"file": [
{
"content": "Hallo"
}
]
}
My models and Serializers
#MODELS
class Story (models.Model):
title = models.CharField(max_length=100,blank=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
class File(models.Model):
story = models.ForeignKey(Story,on_delete=models.CASCADE, null=True)
content = models.TextField(blank=False, null=True)
#SERIALIZER
class TestFileSerializer (serializers.ModelSerializer):
class Meta:
model = File
fields = ('content',)
class StoryCreateUpdateSerializer (serializers.ModelSerializer):
file = TestFileSerializer(many=True)
class Meta:
model = Story
fields = ('title','file')
def create(self, validated_data):
current_user = self.context["request"].user
title = validated_data.pop('title')
file = validated_data.pop('file')
story_instance = Story.objects.create(author=current_user, title=title)
for file_data in file:
File.objects.create(**file_data, story=story_instance)
return story_instance
#VIEW
class StoryCreateUpdateViewSet(viewsets.ModelViewSet):
serializer_class = StoryCreateUpdateSerializer
queryset = Story.objects.all()
I'am happy for any clarification. As i running out of ideas.
Upvotes: 0
Views: 869
Reputation: 396
In ForeignKey field of File model, default related_name
and related_query_name
attributes are 'file_set' not 'file'
So you should do one of these changes on your code:
Method 1:
In File model add related_name
and related_query_name
attributes to ForeignKey field with values 'file':
story = models.ForeignKey(
Story,
on_delete=models.CASCADE,
null=True,
related_name = 'file',
related_query_name = 'file'
)
Method 2:
In StoryCreateUpdateSerializer
change 'file' field to 'file_set':
class StoryCreateUpdateSerializer (serializers.ModelSerializer):
file_set = TestFileSerializer(many=True)
class Meta:
model = Story
fields = ('title','file_set')
def create(self, validated_data):
current_user = self.context["request"].user
title = validated_data.pop('title')
file = validated_data.pop('file')
story_instance = Story.objects.create(author=current_user, title=title)
for file_data in file:
File.objects.create(**file_data, story=story_instance)
return story_instance
In this method, also you've to change your request body properties and substitute 'file' with 'file_set'
Upvotes: 2