我使用 React 作为前端,django 作为后端。
我使用 fetch API 向服务器发送 POST 请求。数据通过 JSON.stringify() 传递。
该请求将被 Django 中的视图拦截,数据可在视图函数的请求参数中获取。至少这是我所理解的。
现在,当我访问
request.body
时,我惊讶地得到了一个字典。令人惊讶的是,序列化器(也是反序列化的工作)尚未发挥作用。那么它是如何自动反序列化的呢?如果这以某种方式起作用,那么需要在序列化器中引入反序列化功能。
前端代码:
export async function AuthHandler(
task,
data,
root_url
) {
task = task==="login"?`${task}/`:''
const resp = await fetch(`${root_url}${task}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data), // what goes from here is string "{ }"
});
const respData = await resp.json();
if (respData['token']){
sessionStorage.setItem('token',respData['token'])
}
console.log(respData)
return respData["token"];
}
后端代码:
class GenericLoginView(generics.GenericAPIView):
queryset = CustomUserModel.objects.all()
serializer_class = UserLoginSerializer
def post(self, request):
token = None
request_data = {
"method": request.method,
"headers": dict(request.headers),
"body": request.data,
"query_params": request.query_params,
"path": request.path,
}
# Print the request as a dictionary
print("Request as Dictionary:", request_data)
print(type(request.data)) # dict
serializer = self.serializer_class(data=request_data["body"])
if serializer.is_valid():
print(serializer.validated_data)
email = serializer.validated_data["email"]
password = serializer.validated_data["password"]
user = authenticate(request, email=email, password=password)
if user:
token = Token.objects.get(user=user).key
else:
print(serializer.error_messages)
return Response({"token": token})
提前致谢...
我厌倦了检查数据类型的
request.data
另外,还查阅了文档。
你观察到的行为是 Django REST framework (DRF) 如何处理传入请求的结果。DRF 不会等待你显式调用反序列化器来解析请求正文。相反,它会在你的视图中自动执行此操作,特别是在你访问
request.data
时。
以下是其工作原理的细分:
-
request.body
中的原始数据: 你所言极是,request.body
包含从你的 React 前端发送的原始字节字符串。 -
DRF 的
request.data
: DRF 的APIView
(你的GenericLoginView
从中继承)具有request
属性的自定义实现。此自定义request
对象(通常是rest_framework.request.Request
的实例)解析并处理传入的数据。它检查Content-Type
标头以确定如何处理请求正文。在你的情况下,它是application/json
。 -
自动解析: 当 DRF 遇到
application/json
时,它会使用 JSON 解析器自动将原始字节字符串反序列化为 Python 字典。这就是为什么你在访问request.data
时会看到一个字典的原因,即使你还没有显式使用你的序列化器。 -
序列化器的作用: 那么你的序列化器(
UserLoginSerializer
)有什么作用?它用于 验证 和 转换 数据,而不是用于初始反序列化。当你实例化serializer = self.serializer_class(data=request_data["body"])
时,DRF 会检查数据是否符合你在序列化器中定义的规则(例如,字段类型、是否必需等)。如果数据有效,serializer.validated_data
将为你提供一个包含已清理和已验证数据的字典,你可以使用该字典进行身份验证。
总而言之,你不需要在 DRF 中显式反序列化 JSON 请求正文。
DRF 会自动为你处理此问题,并提供
request.data
中的解析数据。然后,你的序列化器用于验证和清理此已解析数据。
关于你的代码的一些额外说明:
-
在你的
GenericLoginView
中,你不需要包含request_data
字典中的所有内容。DRF 已经通过request
对象的各种属性(例如request.method
、request.headers
、request.query_params
)提供了对此数据的访问。 - 考虑使用 DRF 的内置身份验证和权限类来简化你的视图。有关详细信息,请参阅 DRF 文档的“身份验证”部分: https://www.django-rest-framework.org/api-guide/authentication/
希望这对你有帮助!如果还有其他问题,请告诉我。
标签:python,django,django-rest-framework,backend,documentation From: 78767388