在 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.jpgname_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_instancemedia 属性给了我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 后更新序列化程序中的值的主要内容,如果未能解决你的问题,请参考以下文章

django使用rest_framework

Django Rest Framework

Django rest framework 身份和权限验证

Django Rest Framework:非模型服务

django-rest-framework - 在可浏览的 API 中自动生成表单?

在 django-rest-framework 中,是不是可以同时使用 oauth 和 session 身份验证?