在 Django Rest Framework 中访问 .data 后更新序列化程序中的值
Posted
技术标签:
【中文标题】在 Django Rest Framework 中访问 .data 后更新序列化程序中的值【英文标题】:Updating a value in serializer after accessing .data in Django Rest Framework 【发布时间】:2019-02-19 22:07:04 【问题描述】:我的Post
类有一个序列化程序,它有一个image
和一个link
属性。
我想:
提交我的帖子数据(文字和图片)
访问提交文件的 url 以用于在其他地方共享它。
找到link
值后更新它。
这是我尝试过的:
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()
这会引发异常。说:
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.
问题是当我使用post.validated_data.get('media')
而不是.data
时,它没有给我网址。它给了我一个InMemoryUploadedFile
对象,当然,它没有任何路径和url。
我以为我可以使用InMemoryUploadedFile
对象的name
属性来查找url(将在.save()
之后创建的那个),但是当名称重复时,磁盘中文件的真实名称和url与它的原始名称不同(例如,name.jpg
和 name_aQySbJu.jpg
),我不能将它用于我的目的。
问题
我如何才能访问该上传文件的 URL,并在我更新我的 post
后调用 save()
?
【问题讨论】:
【参考方案1】:序列化器的save()
方法返回对应的实例。因此,您可以使用它来获取 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()
【讨论】:
谢谢兄弟!我不知道.save()
的返回值。访问post_instance
的media
属性给了我MEDIA_URL
之后的路径,我也必须将我的主机和media_url 添加到它的第一个以访问完整的url。谢谢!【参考方案2】:
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)
实际上,您可以使用这种方法来保存您的帖子。当您通过 serializer_obj.save(**kwargs) 方法传递链接时,它会自动将您的额外数据传递到 create(self,validated_data) 或 update(self,instance,validated_data) 将您的额外数据作为字典添加到 validatad_data 中。因此,您可以在序列化程序的创建或更新方法中处理额外的数据。
【讨论】:
我的问题仍然存在。我无法使用这种方法访问 media_url(访问.validated_data
不起作用,如问题所述。)如果我用.data
替换它,则该异常再次引发,尽管我正在调用save()
关键字参数。
如果validated_data.get('media')
返回一个文件对象,您可以访问媒体网址为media=validated_data.get('media')
,然后media_url = media.url if media else None
。然后您可以使用request.build_absolute_uri(media_url)
生成完整的 url 路径
感谢您的回复,但它给了我 'InMemoryUploadedFile' 对象没有属性 'url'。 它只有 name
与我们的业务相关的属性。
如我所见,built_absolute_uri()
仅将文件名应用到请求的基本 url。正确的?就我而言,此视图适用于 url /api/post
,我的媒体存储在 /media/<user>/<name>
中。我认为这个功能对我没有帮助。
built_absolute_uri()
方法获取 url_path(ex: /media/image.jpg) 并生成完整地址(ex: example.com//media/image.jpg)
以上是关于在 Django Rest Framework 中访问 .data 后更新序列化程序中的值的主要内容,如果未能解决你的问题,请参考以下文章