6
votes

I have a serializer for my Post class which has a image and a link attribute.

media is an FileField and link is a URLField which is a url to somewhere else I share my post (in another website.)

I want to:

  1. Submit my post data (text, and the image)

  2. Accessing the url of submitted file to use in sharing it in another place.

  3. Updating the link value after I found it.

This is what I tried:

post = PostCreateSerializer(data=request.data, context={'request': request})
post.is_valid(raise_excpetions=True)
post.save()
media_url = post.data.get('media')
link = find_link_value(media_url)
post.link = link
post.save()

This raises an exception. says:

 You cannot call `.save()` after accessing `serializer.data`.If you need to access data before committing to the database then inspect 'serializer.validated_data' instead.

The problem is when I use post.validated_data.get('media') instead of .data, it doesn't give me the url. It gives me an InMemoryUploadedFile object, that of course, doesn't have any path and url.

I thought I could use name attribute of InMemoryUploadedFile object to find the url (the one that will be created after .save()), but when the name is duplicate, the real name of file in disk and url differs from it's original name (for example, name.jpg and name_aQySbJu.jpg) and I can't use it for my purpose.

Question

How can I have access to URL of that uploaded file, and also call save() after I updated my post?

2

2 Answers

5
votes

The serializer's save() method return corresponding instance. So, you can use that to get the url

post = PostCreateSerializer(data=request.data, context={'request': request})
post.is_valid(raise_excpetions=True)
post_instance = post.save()
media_url = post_instance.media.url
link = find_link_value()
post_instance.link = link
post_instance.save()
2
votes
post = PostCreateSerializer(data=request.data, context={'request': request})
post.is_valid(raise_excpetions=True)
media_url = post.validated_data.get('media')
link = find_link_value()
post.save(link=link)

Actually, you can use this approach in order to save your post. When you pass link through serializer_obj.save(**kwargs) method it automatically pass your extra data into create(self, validated_data) or update(self, instance, validated_data) adding your extra data into validatad_data as dictionary. So than you can handle your extra data in create or update method of serializer.