I am new to Django and trying to build an app to test out few things for my project. I want to read the form - do some validation and then send the input to another module (say a scheduler running separately). The scheduler rest api will be called with the form data (which is file) and the scheduler will load the data into the models. I am using python requests and serializing data into json before calling the rest api. This is where I am getting error. Django on request.FILES create a InMemoryUploadedFile class which has the data loaded somewhere in memory and serializing this to Json is not straightforward. I tried looking other ways (like image serializers example) but not able to resolve this issue.
我是Django的新手,并试图构建一个应用程序来为我的项目测试一些东西。我想阅读表单 - 做一些验证,然后将输入发送到另一个模块(比如一个单独运行的调度程序)。调度程序rest api将使用表单数据(即文件)调用,调度程序将数据加载到模型中。我在调用其余的api之前使用python请求并将数据序列化为json。这是我收到错误的地方。 Django on request.FILES创建一个InMemoryUploadedFile类,它将数据加载到内存中,并将其序列化为Json并不简单。我尝试了其他方式(如图像序列化示例)但无法解决此问题。
forms.py
class UploadDatasetForm(forms.Form):
docfile = forms.FileField(label='Choose file')
views.py
def test_upload(request):
if request.method == 'POST':
form = UploadDatasetForm(request.POST, request.FILES)
if form.is_valid():
in_file = request.FILES['docfile']
payload = {'doc_file': in_file}
msg = json.dumps(payload)
URL = 'http://localhost:8880/form'
r = requests.post(URL, data=msg)
return HttpResponse(json.dumps(r.text), content_type="application/json")
Error:
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <InMemoryUploadedFile: A_test.csv (text/csv)> is not JSON serializable
Any help here will be appreciated. Thanks a lot.
任何帮助将不胜感激。非常感谢。
2 个解决方案
#1
2
It looks like you're trying to serialize a reference to an InMemoryUploadedFile instance - if you just want to JSON serialize the data and not the whole class instance you could read the data.
看起来您正在尝试序列化对InMemoryUploadedFile实例的引用 - 如果您只是希望JSON序列化数据而不是整个类实例,则可以读取数据。
Replace:
payload = {'doc_file': in_file}
With
payload = {'doc_file': in_file.read()}
You'll want be sure to use chunks() if the data is large: https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
如果数据很大,你肯定要使用chunks():https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
#2
1
By default python only supports of converting a hand full of default datatypes (str, int, float, dict, list, etc.). You try to convert InMemoryUploadedFile, the dumps function doesn't know how to handle that. What you need to do is provide a method to convert the data into one of the data types that python does supports.
默认情况下,python仅支持转换一个充满默认数据类型的手(str,int,float,dict,list等)。您尝试转换InMemoryUploadedFile,转储功能不知道如何处理。您需要做的是提供一种方法将数据转换为python支持的数据类型之一。
class MyJsonEncoder(DjangoJSONEncoder):
def default(self, o):
if isinstance(o, InMemoryUploadedFile):
return o.read()
return str(o)
msg = json.dumps(payload, cls=MyJsonEncoder)
#1
2
It looks like you're trying to serialize a reference to an InMemoryUploadedFile instance - if you just want to JSON serialize the data and not the whole class instance you could read the data.
看起来您正在尝试序列化对InMemoryUploadedFile实例的引用 - 如果您只是希望JSON序列化数据而不是整个类实例,则可以读取数据。
Replace:
payload = {'doc_file': in_file}
With
payload = {'doc_file': in_file.read()}
You'll want be sure to use chunks() if the data is large: https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
如果数据很大,你肯定要使用chunks():https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.chunks
#2
1
By default python only supports of converting a hand full of default datatypes (str, int, float, dict, list, etc.). You try to convert InMemoryUploadedFile, the dumps function doesn't know how to handle that. What you need to do is provide a method to convert the data into one of the data types that python does supports.
默认情况下,python仅支持转换一个充满默认数据类型的手(str,int,float,dict,list等)。您尝试转换InMemoryUploadedFile,转储功能不知道如何处理。您需要做的是提供一种方法将数据转换为python支持的数据类型之一。
class MyJsonEncoder(DjangoJSONEncoder):
def default(self, o):
if isinstance(o, InMemoryUploadedFile):
return o.read()
return str(o)
msg = json.dumps(payload, cls=MyJsonEncoder)