我正在使用此plugin使用jquery上传多个文件,此项目适用于Django,但现在我正在尝试使用App Engine数据存储区。
我成功部署了,直到我尝试上传时才有效,在服务器日志中显示错误消息:
ValueError:App Engine存储后端仅支持BlobstoreFile 实例或文件属性为BlobstoreFile的文件实例。
我认为错误是因为在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)
有什么想法解决它吗?感谢。
答案 0 :(得分:3)
好的,这里有很多值得注意的事情,它们正是App Engine工作原理的核心。
Django的Model层仅用于处理关系数据库,如MySQL,SQLite,Postgres,Oracle等。
App Engine的数据存储区是非关系型的,因此本身不能与Django模型一起使用。但是,您可以使用Django-nonrel,它充当Django模型和非关系数据库(如数据存储区)之间的转换层。
不幸的是,它仍然不是那么简单,因为Django FileField并不完全适合AppEngine BlobProperty。有一些解决方法,但数据存储无论如何都不适合提供图像。
Google推荐两种存储和提供文件的方式,例如图片: Blobstore 和 Google云存储。
最终,存储上传图像的最佳方法是将它们存储在其中一个或另一个中,然后在模型上记录指向图像的链接。因此,如果您将模型更改为:
class Picture(models.Model):
file_url = models.URLField()
slug = models.SlugField(max_length=50, blank=True)
...
在您的视图中,使用here描述的技术将文件上传到Blobstore,然后将upload_url
保存在模型上作为file_url
字段。
您可以对Google云端存储执行相同操作,但由于Blobstore实际上是App Engine的一部分(而不是其他服务中的API),因此它为您提供了各种好处,如下所述。
请注意,如上所述,这仅在您使用Django-nonrel时有效,否则您将无法将Django模型保存到数据存储区。
使用Django-nonrel,您可以按原样将上面的模型保存在数据存储区中。然而,Django-nonrel有许多需要习惯的警告,而且可能很慢。我个人不会推荐它用于新项目,但其他人可能不同意。
或者,您可以回避Django的模型层并使用App Engine's own Model layer,它旨在与数据存储区完美匹配。它包含用于引用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的紧密集成。
如果您想使用Django模型但又不想使用Django-nonrel,还有另一种选择。如果您愿意放弃非关系数据存储的好处,可以使用Google Cloud SQL代替。 Django原生支持Cloud SQL。但是,Google Cloud SQL目前的预览范围有限,因此您可能会发现很难获得访问权限。
如果您决定使用Cloud SQL,如果您希望公开提供,则仍应将图像存储在Blobstore或Google Cloud Storage中,如上所述。