通过令牌检索用户时,我应该使用什么url结构?

时间:2017-07-31 08:47:17

标签: django django-rest-framework

我正在使用Django Rest Framework来处理学校移动应用程序的令牌身份验证。特别是,当学生登录时,移动应用程序将令牌发送到我的Django后端,然后后端组合来自其数据库的数据和来自其他来源的一些外部数据。我发现最简单的方法是使用通用的RetrieveAPIView来完成我需要的工作。

我的代码正常运行,我的主要问题是网址。对于大多数检索,我们通常也有主键(例如/ students / SOME-ID),但在这种情况下,我使用令牌来检索用户而不是主键。事实上,如果传入的SOME-ID与令牌不同,那么与令牌关联的用户无论如何都会被返回(这看起来有点奇怪)。

我想知道让我的网址路径只是(/学生)是否更好,尽管这似乎是一个列表而不是检索操作。

我现在有什么

http://localhost:8000/api/v1/revision/students/1

这是更好的

http://localhost:8000/api/v1/revision/students/

CODE

class StudentView(generics.RetrieveAPIView):
    model = Student
    serializer_class = StudentSerializer

    # combines data from both current and legacy database
    def retrieve(self, request, pk=None):
        obj = get_object_or_404(Student, user=request.user)
        # KIV -> unsure if this is the best way to combine data from legacy and current database
        # or should it be done in the serializer
        data = StudentSerializer(obj).data

        # combines existing data stored in database with legacy data from database
        legacy_data = SOME_EXTERNAL_API_SERVICE.get_student_info(obj) 
        data['avatar'] = legacy_data['avatar']
        data['coins'] = legacy_data['coins']
        return Response(data)

2 个答案:

答案 0 :(得分:1)

当然,网址http://localhost:8000/api/v1/revision/students/看起来更好。

但是你不需要在RetrieveAPIView中写这个,你总是可以在基础APIView中执行此操作,

class StudentView(APIView):

    def get(self, request, *args, **kwargs):
        obj = get_object_or_404(Student, user=request.user)
        data = StudentSerializer(obj).data
        legacy_data = SOME_EXTERNAL_API_SERVICE.get_student_info(obj) 
        data['avatar'] = legacy_data['avatar']
        data['coins'] = legacy_data['coins']
        return Response(data)

通过这样使用,您可以避免使用网址中的额外pk关键字参数。

答案 1 :(得分:1)

我绝对不会将/students/id/用于您所描述的行为:此网址应始终返回给定id错误的学生(具体取决于是否允许用户提取此资源)这样做)。您可能希望将此URL用于管理员以便将来查看学生。

出于同样的原因,我不会使用/students/,因为我希望它能够返回所有学生的列表,或者至少是允许特定登录用户看到的所有学生的列表。这可能适合您的目的(登录用户只能看到自己),但如果您创建可以查看更多学生的新角色,将来可能不会这样。

这里有两种方法:

  • 您可以将此视为所有学生的过滤器:/students/?current=true我个人觉得这很难看,因为您实际上并没有过滤整套学生。
  • 或者您将此视为一种特殊情况:/students/current使用特殊关键字来获取此特定学生。

我会选择后者,因为在查看API时它更具描述性且更易于理解。当然注意id在这种情况下永远不会是'当前',这就是为什么有些人不鼓励这种特殊资源查询并选择第一个选项。