首页 > 编程 > Python > 正文

Django REST为文件属性输出完整URL的方法

2020-02-16 11:07:40
字体:
来源:转载
供稿:网友

前言

我的 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)            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表