我正在使用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)
答案 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
在这种情况下永远不会是'当前',这就是为什么有些人不鼓励这种特殊资源查询并选择第一个选项。