1

我正在使用这个插件用 jquery 上传多个文件,这个项目是为 Django 设计的,但现在我正在尝试使用 App Engine 数据存储区。

我已成功部署,并且在我尝试上传之前一直有效,服务器日志中显示一条错误消息:

ValueError:App Engine 存储后端仅支持 BlobstoreFile 实例或文件属性为 BlobstoreFile 的 File 实例。

我认为错误是因为在 models.py 中它使用了 django 的模型类,即models.FileField,但 AppEngine 需要db.BlobProperty().

这是项目链接:https ://github.com/sigurdga/django-jquery-file-upload

这是我的 models.py 文件:

from django.db import models

class Picture(models.Model):

    # This is a small demo using FileField instead of ImageField, not
    # depending on PIL. You will probably want ImageField in your app.
    file = models.FileField(upload_to="pictures")
    slug = models.SlugField(max_length=50, blank=True)

    def __unicode__(self):
        return self.file

    @models.permalink
    def get_absolute_url(self):
        return ('upload-new', )

    def save(self, *args, **kwargs):
        self.slug = self.file.name
        super(Picture, self).save(*args, **kwargs)

有什么想法可以解决吗?谢谢。

4

1 回答 1

3

好的,这里有许多值得注意的事情,它们直接涉及 App Engine 工作原理的核心。

Django 的模型层仅设计用于关系数据库,如 MySQL、SQLite、Postgres、Oracle 等。

App Engine 的数据存储区是非关系型的,因此不能与原生的 Django 模型一起使用。但是,您可以使用Django-nonrel,它充当 Django 模型和非关系数据库(如 Datastore)之间的转换层。

不幸的是,它仍然没有那么简单,因为 Django FileField 并不完全适合 AppEngine BlobProperty。有一些变通方法,但数据存储区无论如何都不能很好地提供图像。

存储图像

Google 推荐 2 种存储和提供文件(例如图像)的方式:BlobstoreGoogle Cloud Storage

最终,存储上传图像的最佳方法是将它们存储在其中一个或其他中,然后在模型上记录指向图像的链接。因此,如果您将模型更改为:

class Picture(models.Model):

    file_url = models.URLField()
    slug = models.SlugField(max_length=50, blank=True)

    ...

在您看来,使用此处描述的技术将文件上传到 Blobstore,然后将upload_url模型上的 保存为file_url字段。

您可以使用 Google Cloud Storage 执行相同的操作,尽管 Blobstore 实际上是 App Engine 的一部分(而不是其他服务的 API),它为您提供了各种好处,如下所述。

请注意,如上所述,这仅在您使用 Django-nonrel 时才有效,否则您将无法将 Django 模型保存到数据存储区。

存储模型

使用 Django-nonrel,您可以将上面的模型按原样保存在数据存储中。但是,Django-nonrel 有许多需要习惯的警告,而且速度可能很慢。我个人不会将它推荐给新项目,但其他人可能不同意。

或者,您可以避开 Django 的模型层并使用App Engine 自己的模型层,该模型层旨在与数据存储区完美匹配。它包括用于引用 Blobstore 中的对象的特定属性类型。您的模型可能如下所示:

from google.appengine.ext.blobstore import blobstore
from google.appengine.ext import db

class Picture(db.Model):

    file = blobstore.BlobReferenceProperty()
    slug = db.StringProperty(required=False)

    ...

BlobReferenceProperty为您提供了比仅存储 URL 更多的功能,因为您可以通过此属性访问文件数据本身,以获取有关文件的数据(大小等)或处理它。如果您对仅存储 URL 感到满意,那么还有一个db.LinkProperty类似于 Django 的models.URLField.

当然,使用 App Engine 模型而不是 Django 模型会失去 Django 模型层的许多好处以及它提供的与 Django 的紧密集成。

谷歌云 SQL

如果您想使用 Django 模型但不想使用 Django-nonrel,还有另一种选择。如果您乐于放弃非关系型数据存储的优势,您可以改用Google Cloud SQL。Django 原生支持 Cloud SQL。但是,Google Cloud SQL 目前处于有限预览阶段,因此您可能会发现很难访问。

如果您决定使用 Cloud SQL,如果您希望公开提供图像,则仍应将图像存储在 Blobstore 或 Google Cloud Storage 中,如上所述。

于 2012-05-20T16:00:09.887 回答