use*_*619 2 python django python-requests django-rest-framework
我试图使用Python请求模块将一些数据和文件发送到我的django rest应用程序但是得到以下错误.
raise MultiPartParserError('Invalid boundary in multipart: %s' % boundary)
MultiPartParserError: Invalid boundary in multipart: None
Run Code Online (Sandbox Code Playgroud)
码:-
import requests
payload={'admins':[
{'first_name':'john'
,'last_name':'white'
,'job_title':'CEO'
,'email':'test1@gmail.com'
},
{'first_name':'lisa'
,'last_name':'markel'
,'job_title':'CEO'
,'email':'test2@gmail.com'
}
],
'company-detail':{'description':'We are a renowned engineering company'
,'size':'1-10'
,'industry':'Engineering'
,'url':'http://try.com'
,'logo':''
,'addr1':'1280 wick ter'
,'addr2':'1600'
,'city':'rkville'
,'state':'md'
,'zip_cd':'12000'
,'phone_number_1':'408-393-254'
,'phone_number_2':'408-393-221'
,'company_name':'GOOGLE'}
}
files = {'upload_file':open('./test.py','rb')}
import json
headers = {'content-type' : 'application/json'}
headers = {'content-type' : 'multipart/form-data'}
#r = requests.post('http://127.0.0.1:8080/api/create-company-profile/',data=json.dumps(payload),headers=headers,files=files)
r = requests.post('http://127.0.0.1:8080/api/create-company-profile/',data=payload,headers=headers,files=files)
print r.status_code
print r.text
Run Code Online (Sandbox Code Playgroud)
Django代码: -
class CompanyCreateApiView(CreateAPIView):
parser_classes = (MultiPartParser, FormParser,)
def post(self, request, *args, **kwargs):
print 'request ==', request.data
Run Code Online (Sandbox Code Playgroud)
好的,我忘记了你的标题.根据规格:
Run Code Online (Sandbox Code Playgroud)Content-Type = "Content-Type" ":" media-typeMIME提供了许多"多部分"类型 - 单个消息体内的一个或多个实体的封装.所有多部分类型共享一个通用语法,...并且必须包含边界参数作为媒体类型值的一部分.
以下是包含multipart/form-data的请求:
POST /myapp/company/ HTTP/1.1
Host: localhost:8000
Content-Length: 265
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.9.0
Connection: keep-alive
Content-Type: multipart/form-data; boundary=63c5979328c44e2c869349443a94200e
--63c5979328c44e2c869349443a94200e
Content-Disposition: form-data; name="hello"
world
--63c5979328c44e2c869349443a94200e
Content-Disposition: form-data; name="mydata"; filename="data.txt"
line 1
line 2
line 3
line 4
--63c5979328c44e2c869349443a94200e--
Run Code Online (Sandbox Code Playgroud)
查看数据部分如何按边界分隔:
--63c5979328c44e2c869349443a94200e--
Run Code Online (Sandbox Code Playgroud)
我们的想法是将某些东西用于不太可能出现在数据中的边界.请注意,边界包含在Content-Type请求的标头中.
该请求由此代码生成:
import requests
myfile = {'mydata': open('data.txt','rb')}
r = requests.post(url,
#headers = myheaders
data = {'hello': 'world'},
files = myfile
)
Run Code Online (Sandbox Code Playgroud)
看起来您正在仔细关注django-rest-framework 文档中的以下注释:
注意:在开发客户端应用程序时,请始终记住确保在HTTP请求中发送数据时设置Content-Type标头.
如果您没有设置内容类型,大多数客户端将默认使用'application/x-www-form-urlencoded',这可能不是您想要的.
但是当你使用时requests,如果你Content-Type自己指定标题,那么requests假设你知道你正在做什么,并且它不会Content-Type用Content-Type它本来提供的标题覆盖你的标题.
您没有在Content-Type标题中提供边界- 根据需要.你怎么能?您没有组装请求的主体并创建边界来分隔各种数据,因此您无法知道边界是什么.
当django-rest-framework笔记说您应该Content-Type在请求中包含标题时,这意味着:
您或用于创建请求的任何程序都需要包含
Content-Type标题.
所以@AChampion在评论中是完全正确的:在所有文档广告之后requests提供:Content-Type headerrequests
请求从Python HTTP/1.1中获取所有工作
requests是这样的:如果你提供一个files关键字arg,那么请求使用Content-Type标题,multipart/form-data并在标题中指定一个边界; 然后requests使用边界组装请求的主体.如果你提供了一个data关键字参数,然后请求使用Content-Type的application/x-www-form-urlencoded,这只不过是组装的所有键和值的字典成这种格式:
x=10&y=20
Run Code Online (Sandbox Code Playgroud)
无需边界.
而且,如果你同时提供files关键字ARG和data关键字ARG,然后请求使用Content-Type的multipart/form-data.