Django REST为文件属性输出完整URL的方法
作者:TUALATRIX 发布时间:2023-07-29 02:42:42
前言
我的 App 项目的 API 部分是使用 Django REST Framework 来搭建的,它可以像搭积木一样非常方便地搭出 API,兼具方便和灵活。
django是一个神奇的框架,而restframework又是遵循了这个框架的另一个神奇的框架,然而由于restframework的文档稀烂无比,很多时候你必须看源码才能写出科学的代码,这挡住了很多新手的路。
在使用的过程中我也积累了一些小技巧,这里写一则关于如何为文件属性输出完整 URL 的字段。
实现方法
一个典型的案例是,当请求 /profile/ 这个 API 的时候,返回类似于这样的结果:
{
"id": 1,
"nickname": "管理员",
"mobilephone": "1234567890",
"avatar": "/media/profiles/2017/12/17/avatar.png"
}
在 Django REST 的定义中,我使用了自定义的一个扩展自 rest_framework.views.APIView 的 ProfileView 类型,实现了它的 get 方法,来给认证的用户返回一个 Profile 对象:
class ProfileView(APIView):
def get(self, request):
user = request.user
if user.is_authenticated:
profile = Profile.objects.get(user=user)
return Response(ProfileSerializer(profile).data)
else:
raise exceptions.AuthenticationFailed('Not authenticated user!')
这里的逻辑很简单,判断请求当前 API 的用户是不是已经验证过的用户,如果是的话,再得到它的 Profile,再通过 ProfileSerializer 把 profile 实例序列化成 JSON 对象。如果不是已验证用户,则会返回 401 验证失败相关信息。
以上输出的内容,交给 Web 前端使用是没什么问题的,但如果是给 App 使用,那么 avatar 这个文件属性的相对 URL 不太合适,于是我们要改造一下这个 API,使其能输出绝对 URL。
如何做呢?只需要将上面的 get 方法,稍加修改即可:
-class ProfileView(APIView):
+class ProfileView(generics.GenericAPIView):
parser_classes = (MultiPartParser, FormParser)
+ serializer_class = ProfileSerializer
def get(self, request):
user = request.user
if user.is_authenticated:
profile = Profile.objects.get(user=user)
- return Response(ProfileSerializer(profile).data)
+ serializer = self.get_serializer(profile)
+ return Response(serializer.data)
else:
raise exceptions.AuthenticationFailed('Not authenticated user!')
不同于之前继承自 APIView,现在继承自 generics.GenericAPIView,这是一个更通用的类,可以看到,这里通过手动构建 ProfileSerializer 改成通过 self.get_serializer 来进行,这里有什么不同呢?
还得看看 Django REST 的源码,GenericAPIView 这个类的 get_serializer 在做什么。
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
可以看到,这个方法在创建 serializer 的时候,会把 context 传进去,而 get_serializer_context 也是一个固定方法,它会把 request、view 和 format 这些信息包含在里面。
那么 request、view 和 format 这些信息,是如何用在 serializer 里面,最后把一个文件对象的全路径展开的呢?
省略中间 serializer 一系列序列化过程,当它遇到 FileField 的时候,会通过判断 context 里面有没有 reuqest,有的话,就调用 request.build_absolute_uri(url) 方法,把绝对地址 build 出来,而不是默认存在数据库里的相对地址。
def to_representation(self, value):
if not value:
return None
use_url = getattr(self, 'use_url', api_settings.UPLOADED_FILES_USE_URL)
if use_url:
if not getattr(value, 'url', None):
# If the file has not been saved it may not have a URL.
return None
url = value.url
request = self.context.get('request', None)
if request is not None:
return request.build_absolute_uri(url)
return url
return value.name
这就是为什么通过 GenericAPIView 来输出 API 对象,文件属性默认有绝对路径而不是相对路径的原因了~
来源:https://imtx.me/archives/2397.html
猜你喜欢
- Python中使用threading.Condition交替打印两个字符的程序。这个程序涉及到两个线程的的协调问题,两个线程为了能够相互协调
- 本文实例为大家分享了python实现名片管理系统的具体代码,供大家参考,具体内容如下名片管理系统前提:实现名片管理系统,首先要创建两个pyt
- 本文实例为大家分享了python学生管理系统的具体代码,供大家参考,具体内容如下基于列表存储的学生管理系统,实现如下功能==========
- 把函数作为参数的用法比较直观:def func(a, b): return a + bdef test(f, a, b): print f
- 判断字符串长度函数:<SCRIPT LANGUAGE="JavaScript"><!--fu
- 更改主题File → Settings → Appearance & Behavior → Appearance → Theme结果
- 关于建立索引的几个准则:1、合理的建立索引能够加速数据读取效率,不合理的建立索引反而会拖慢数据库的响应速度。2、索引越多,更新数据的速度越慢
- 题目:如何在python中实现整数的二进制循环移位?概述在python中,可以通过<<以及>>运算符实现二进制的左移
- 1.下载python2.7.xwget https://www.python.org/ftp/python/2.7.6/Python-2.7
- 在Python自带的编辑器IDLE中或者Python shell中不能使用cd命令,那么跳到目标路径呢。方法是使用os包下的相关函数实现路径
- 这篇文章主要介绍了JavaScript对象属性操作实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- #!/usr/bin/env python# -*- coding: utf8 -*-import MySQLdbimport timeim
- mysql-proxy实现读写分离MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测、
- 数据集介绍《悲惨世界》中的人物关系图,图中共77个节点、254条边。数据集截图:打开README文件:Les Misérables netw
- 本文实例为大家分享了Vue实现简单跑马灯特效的具体代码,供大家参考,具体内容如下效果:点击按钮让文字动起来,点击停止按钮让文字停止知识点:s
- 1.表达式操作符Table 1 算术操作符操作符 语法 含义+ a + b 相加 - a - b 相减 - - a
- 为了给导航栏添加响应式特性,您要折叠的内容必须包裹在带有 classes .collapse、.navbar-collapse 的 <
- 前言这几年对运维人员来说最大的变化可能就是公有云的出现了,我相信可能很多小伙伴公司业务就跑在公有云上, 因为公司业务关系,我个人
- 在数据分析中经常需要从csv格式的文件中存取数据以及将数据写书到csv文件中。将csv文件中的数据直接读取为 dict 类型和 DataFr
- 首先说明一下SQL Server内存占用由哪几部分组成。SQL Server占用的内存主要由三部分组成:数据缓存(Data Buffer)、