Django REST: Uploading and serializing multiple images
You have read_only
set to true in TaskImageSerializer
nested field. So there will be no validated_data there.
Description for the issue
The origin of the exception was a KeyError
, because of this statement
images_data = validated_data.pop('images')
This is because the validated data has no key images
. This means the images input doesn't validate the image inputs from postman.
Django post request store InMemmoryUpload
in request.FILES
, so we use it for fetching files. also, you want multiple image upload at once. So, you have to use different image_names while your image upload (in postman).
Change your serializer
to like this:
class TaskSerializer(serializers.HyperlinkedModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
images = TaskImageSerializer(source='taskimage_set', many=True, read_only=True)
class Meta:
model = Task
fields = ('id', 'title', 'user', 'images')
def create(self, validated_data):
images_data = self.context.get('view').request.FILES
task = Task.objects.create(title=validated_data.get('title', 'no-title'),
user_id=1)
for image_data in images_data.values():
TaskImage.objects.create(task=task, image=image_data)
return task
I don't know about your view, but I'd like to use ModelViewSet
preferrable view class
class Upload(ModelViewSet):
serializer_class = TaskSerializer
queryset = Task.objects.all()
Postman console:
DRF result:
{
"id": 12,
"title": "This Is Task Title",
"user": "admin",
"images": [
{
"image": "http://127.0.0.1:8000/media/Screenshot_from_2017-12-20_07-18-43_tNIbUXV.png"
},
{
"image": "http://127.0.0.1:8000/media/game-of-thrones-season-valar-morghulis-wallpaper-1366x768_3bkMk78.jpg"
},
{
"image": "http://127.0.0.1:8000/media/IMG_212433_lZ2Mijj.jpg"
}
]
}
UPDATE
This is the answer for your comment.
In django reverse foreignKey
are capturing using _set
. see this official doc. Here, Task
and TaskImage
are in OneToMany
relationship, so if you have one Task
instance, you could get all related TaskImage
instance by this reverse look-up
feature.
Here is the example:
task_instance = Task.objects.get(id=1)
task_img_set_all = task_instance.taskimage_set.all()
Here this task_img_set_all
will be equal to TaskImage.objects.filter(task_id=1)