【问题标题】:uploading files with urllib to a FileField model in Django使用 urllib 将文件上传到 Django 中的 FileField 模型
【发布时间】:2013-06-01 19:04:38
【问题描述】:

我有一个 django 文件模型,它有一个 models.FileField 字段和一个用于将文件上传到服务器的表单:

class UploadFile(model.Model):
    filename = models.FileField(upload_to='uploads')
    description = models.CharField(max_length=38, blank=True)

class UploadFileForm(ModelForm):
    class Meta:
        model = UploadFile
        fields = ('filename', 'description')

视图函数如下所示:

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            new_file = form.save()

现在我想要一个 python 脚本,它只使用标准库使用上面的视图函数将文件上传到 UploadFile 模型。但是此代码不起作用,因为 POST 请求没有 FILES 方法。

import urllib, urllib2
data = urllib.urlencode({'filename': open(uploadfile, "rb"),
                        'description': 'upload test'})
post_req = urllib2.Request(upload_file_url, data)
result = urllib2.urlopen(post_req)

如何在 POST 请求中添加 FILES 方法以使用 python 脚本上传文件?我还尝试编写一个不使用表单但也不起作用的不同视图函数。

【问题讨论】:

  • 我将使用 scp 将文件复制过来,直到我能获得有关此问题的帮助

标签: python django urllib2 urllib


【解决方案1】:

要查看您的 django 视图是否有效,您可以使用浏览器对其进行测试:

<FORM action="{{ upload_file_url }}"
      enctype="multipart/form-data"
      method="POST">
  Description: <INPUT type="text" name="description" value="upload test"><BR>
  File to upload: <INPUT type="file" name="filename"><BR>
  <INPUT type="submit" value="Send">
</FORM>

complicated 仅使用 stdlib 以编程方式复制它。

要将文件上传为multipart/form-data,您可以使用requests library

import requests

response = requests.post(upload_file_url,
                         files={'filename': open(uploadfile,'rb'),
                                'description': 'upload test'})
print response.content

urllib2poster 库:

import urllib2

import poster.encode
import poster.streaminghttp

opener = poster.streaminghttp.register_openers()

params = {'filename': open(uploadfile,'rb'), 'description': 'upload test'}
datagen, headers = poster.encode.multipart_encode(params)
response = opener.open(urllib2.Request(upload_file_url, datagen, headers))
print response.read()

【讨论】:

  • 谢谢,我以后可能要使用 requests 库。目前我正在使用 urllib.urlencode 对 postscript 文件进行编码,因为这是我所需要的,但它不适用于二进制文件......
  • @MigueldeVal-Borro:urlencode() 创建 x-www-form-urlencoded 数据,但 django 的 FileField 需要 multipart/form-data。它应该适用于任何文件。您的视图是否适用于我发布的 html 表单?
  • @JF Sebastian 是的,我有一个类似的表格。我还需要对 stdlib 做同样的事情,所以我发送类似 urllib.urlencode({"filename": "plot.ps", "data": f.read(), "description": "test upload"}) 的内容并定义一个视图函数,将数据存储在模型中,并将文件存储在磁盘上。
  • @MigueldeVal-Borro:如果您无法安装任何依赖项,那么只需将海报的源代码添加到您的包中(它是pure Python,不需要额外的依赖项)。
  • 别忘了关闭uploadfile文件?
【解决方案2】:

没那么容易,不是request 没有FILES 方法(这不是方法,是字典)。问题是如果请求没有Content-Type:multipart/form-data,Django 将无法识别文件。

请注意,仅当请求方法为 POST 并且发布到请求的方法为 enctype="multipart/form-data" 时,FILES 才会包含数据。否则,FILES 将是一个类似字典的空白对象。

在这里你可以看到这样的请求是什么样子的:What should a Multipart HTTP request with multiple files look like?

https://docs.djangoproject.com/en/dev/ref/request-response/

所以基本上你要做的就是将该字段添加到你正在构建的请求中并稍后将其发送到 django。

您可以查看 django 文档中的此页面以获取有关此内容的更多信息,如果您可以在将请求发送到 django 之前嗅探或查看请求的情况,那就太好了,这样您就可以知道缺少什么。

https://docs.djangoproject.com/en/dev/ref/forms/api/

由于没有一个简单/直接的答案,我希望这可以让你朝着正确的方向前进。

祝你好运!

【讨论】:

  • 我想我错过了如何将 FILES 添加到使用 urllib2 创建的请求中
  • 好的,您不必在请求中添加FILES 字典。您必须正确地符合请求,当 Django 解析它时,它会自行填充 request.FILES 字典。
猜你喜欢
  • 1970-01-01
  • 2021-05-21
  • 2011-12-12
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2018-04-18
  • 2021-11-04
  • 2018-03-23
相关资源
最近更新 更多