1

我正在为在 Google App Engine 上运行的 Django 应用程序(普通 Django 1.4,而不是非 rel 版本)实现图像上传功能。上传的图像被包装在一个 Django 模型中,该模型允许用户添加标题和搜索标签等属性。

上传是通过函数调用创建 Blobstore 上传 url 来执行的blobstore.create_upload_url(url)。函数参数是上传完成时 Bobstore 重定向到的 url。我希望这是默认 Django 表单处理程序的 url,该处理程序执行包装图像的模型的保存/更新,因此我不必为表单验证、错误报告和数据库更新重复默认 Django 行为。

我尝试提供reverse('admin:module_images_add')给,create_upload_url()但这不起作用,因为它会抛出一个[Errno 30] Read-only file system exception. 我认为这源于默认的 Django 表单处理程序再次尝试以标准 Django 方式上传文件,但随后撞到了 Google App Engine 的砖墙,不允许访问文件系统。

目前,我认为在不重复代码的情况下使其工作的唯一方法是严格分离进程:一个用于定义图像模型实例,第二个用于上传实际图像。不是很直观。

另请参阅我之前发布的这个问题和答案

关于如何使用一种表单和重用 Django 默认表单处理程序来使其工作的任何建议?

编辑:

我一直在阅读装饰器(我对 Python 比较陌生),从我阅读的内容来看,装饰器似乎能够修改现有 Python 代码的行为。是否可以更改现有表单处理程序的运行时行为以使用装饰器解决上述问题?我显然必须 (1) 开发装饰器并 (2) 将其附加到默认处理程序。我不确定(2)是否可能,因为它必须在运行时完成。我无法修补在 GAE 上运行的 Django 代码...

4

1 回答 1

1

好吧,我终于设法让这个工作。如果有人也遇到这种情况,这就是我所做的:

(1) 我ImageFile从模型中删除了该属性。它最终导致 Django 尝试从文件系统上传文件,这在 GAE 中是不允许的。

(2) 我在我的模型中添加了一个 Blobstore 密钥,它基本上是 GAE BlobStore blob 的密钥,并且需要能够在稍后阶段提供图像。附带说明:使用 GAE SDK 时,此属性的长度有限,但在 GAE 生产中要长得多。我最终TextField为它定义了一个。

(3)storage.py与 Daniel Roseman 对这个问题的改编一起使用并将. 它将确保 Blobstore 密钥存在于请求中,以便您与模型一起保存。BlobstoreFileUploadHandlerSETTINGS.PY

(4) 我创建了一个包含ImageField命名“图像”的自定义管理表单。这是必需的,因为它允许您选择文件。它ImageField实际上是“虚拟的”,因为它在表单上的唯一目的是让我选择一个文件进行上传。根据(1),这是至关重要的。

(5) 我重写render_change_form()了我的ModelAdmin类的方法,该方法将准备一个 Blobstore 上传 url。上传 url 有两个版本:一个用于添加新图像,一个用于保存对现有图像的更改。上传 url 通过上下文对象传递给模板。

(6) 我修改了change_form.html(5) 中的 Blobstore 上传 url 作为表单的操作。

(7)save_model()我重写了我的 ModelAdmin 的方法:

def save_model(self, request, obj, form, change):
    if request.FILES.has_key("blobkey"):
        blob_key = request.FILES["blobkey"].blobstore_info._BlobInfo__key
        obj.blobstore_key = blob_key
    super(PhotoFeatureAdmin, self).save_model(request, obj, form, change)

这允许我检索上传处理程序设置的 blob 键并将其设置为我的模型的属性。

对于图像模型的删除,我添加了一个由模型的删除信号触发的特殊功能。这将使 Blobstore 与应用中的图像模型保持同步。

而已。以上允许将图像上传到 GAE 的 blob 存储,其中每个 blob 都整齐地包装在管理员用户可以维护的 Django 模型对象中。好处是不需要复制标准的 Django 行为,并且图像的模型对象将来可以很容易地使用属性进行扩展。

最后一句话:在我看来,考虑到上述情况,GAE 上的普通 Django 中对 blob 的支持目前非常差。实现这一点应该容易得多,而不必依赖 Django 非相关代码和相当长的修改列表;或者,谷歌应该在他们的开发者文档中说明这一点。除非我错过了什么,否则这是无证领域。

于 2013-04-21T00:52:36.970 回答