如何通过Django REST API传输Pickle后的Pandas DataFrame至BinaryField
解决DRF中BinaryField无法保存base64编码Pandas DataFrame的问题
我之前也踩过DRF处理BinaryField的坑,你的问题核心很明确:Django REST Framework(v3.9.4)默认没有为models.BinaryField提供对应的序列化字段,直接用HyperlinkedModelSerializer的话,根本没法正确解析你发送的base64编码数据,最终导致df_object字段存为Null。
下面是具体的解决方案,分两步走:
1. 自定义BinaryField的序列化字段
我们需要写一个自定义字段类,专门处理base64字符串和二进制数据之间的转换,覆盖DRF默认的字段处理逻辑。修改你的serializers.py:
from rest_framework import serializers from .models import DataFrame import base64 class Base64BinaryField(serializers.Field): def to_representation(self, value): # 序列化:把数据库里的二进制数据转成base64字符串返回给前端 if value is None: return None return base64.b64encode(value).decode('utf-8') def to_internal_value(self, data): # 反序列化:把前端传来的base64字符串转成二进制数据,存入数据库 try: return base64.b64decode(data) except ValueError: raise serializers.ValidationError("Invalid base64 encoding") class DataFrameSerializer(serializers.HyperlinkedModelSerializer): # 指定df_object使用我们自定义的字段 df_object = Base64BinaryField(allow_null=True, required=False) class Meta: model = DataFrame fields = ('__all__')
这个自定义字段的作用:
to_internal_value:处理POST请求时的输入数据,把你发送的base64字符串解码成二进制,这样就能正确存入models.BinaryFieldto_representation:处理GET请求时的输出数据,把数据库里的二进制转成base64字符串返回,方便后续前端或其他服务解析
2. 调整客户端发送代码(可选但推荐)
你的客户端代码里,base64.b64encode()返回的是bytes类型,虽然requests会自动处理,但最好显式转成字符串,避免潜在的编码问题:
import pandas as pd import pickle import base64 import requests df = pd.DataFrame({'a': [0, 1, 2, 3]}) pickled = pickle.dumps(df) # 把bytes类型的base64编码转成utf-8字符串 pickled_b64 = base64.b64encode(pickled).decode('utf-8') r = requests.post('http://www.foreignserver.com/api/DataFrame/', data={'df_object': pickled_b64}) # 打印响应信息,确认是否成功 print(r.status_code) print(r.json())
验证数据是否正确保存
发送请求后,你可以通过两种方式验证:
- 直接查看数据库的
df_object字段,应该能看到二进制数据 - 调用API获取这条记录,解码后反序列化成DataFrame:
# 假设你拿到了返回的记录数据 response_data = r.json() b64_data = response_data['df_object'] binary_data = base64.b64decode(b64_data) restored_df = pickle.loads(binary_data) print(restored_df)
输出应该和你最初的DataFrame一致。
内容的提问来源于stack exchange,提问作者Jaco
相关产品推荐
相关产品推荐

