在App Engine上从Django上传到Google云端存储

时间:2022-09-12 19:16:07

I'm using Django 1.5 on Google App Engine and I'm trying to upload files to Google Cloud Storage. I'm using the gcs the library and have written a custom file upload handler that I've registered in settings.py as my only file uploader. I can see my file being correctly uploaded in the blobstore viewer in my development environment but once form.save() is called in views.py I get an exception thrown saying that it's a read only file system? I know Google App Engine doesn't allow access to the file system which is why I'm using GCS in the first place!

我在Google App Engine上使用Django 1.5,我正在尝试将文件上传到Google云端存储。我正在使用gcs库并编写了一个我在settings.py中注册的自定义文件上传处理程序作为我唯一的文件上传器。我可以看到我的文件正在我的开发环境中的blobstore查看器中正确上传,但是一旦在views.py中调用了form.save(),我会抛出一个异常,说它是一个只读文件系统?我知道Google App Engine不允许访问文件系统,这就是我首先使用GCS的原因!

Is there something I need to do to stop Django from trying to save the file to disk?

我是否需要做些什么来阻止Django尝试将文件保存到磁盘?

The relevant code is attached in this gist.

相关代码附在此要点中。

Thanks :)

Stack Trace:

Environment:


Request Method: POST
Request URL: http://localhost:8080/cms/media/add

Django Version: 1.5
Python Version: 2.7.5
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.staticfiles',
 'django.contrib.messages',
 'api',
 'cms',
 'frontend')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Traceback:
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/contrib/auth/decorators.py" in _wrapped_view
  25.                 return view_func(request, *args, **kwargs)
File "/Users/james/Dropbox/University/Year 4/Advanced Development/assignment/cms/views.py" in media_add_or_edit
  44.             form.save()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/forms/models.py" in save
  370.                              fail_message, commit, construct=False)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/forms/models.py" in save_instance
  87.         instance.save()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/base.py" in save
  546.                        force_update=force_update, update_fields=update_fields)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/base.py" in save_base
  650.                 result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/manager.py" in _insert
  215.         return insert_query(self.model, objs, fields, **kwargs)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/query.py" in insert_query
  1673.     return query.get_compiler(using=using).execute_sql(return_id)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/sql/compiler.py" in execute_sql
  936.         for sql, params in self.as_sql():
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/sql/compiler.py" in as_sql
  894.                 for obj in self.query.objs
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/fields/files.py" in pre_save
  250.             file.save(file.name, file, save=False)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/db/models/fields/files.py" in save
  86.         self.name = self.storage.save(name, content)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/core/files/storage.py" in save
  48.         name = self._save(name, content)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/django-1.5/django/core/files/storage.py" in _save
  198.                     fd = os.open(full_path, flags, 0o666)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/tools/devappserver2/python/stubs.py" in fake_open
  71.     raise OSError(errno.EROFS, 'Read-only file system', filename)

Exception Type: OSError at /cms/media/add
Exception Value: [Errno 30] Read-only file system: u'/Users/james/Dropbox/University/Year 4/Advanced Development/assignment/IMG_0746.jpg'

1 个解决方案

#1


2  

I eventually solved this by moving the FileField from my Model into my ModelForm like so:

我最终通过将FileField从我的模型移动到我的ModelForm中来解决这个问题:

# Used for uploading media that forms part of a story
class Media(models.Model):
    title = models.CharField(max_length=100)
    type = models.CharField(max_length=5, choices=MEDIA_TYPES)
    content = models.TextField()
    date_created = models.DateTimeField(auto_now_add=True)

# Used to convert the media model to a form in the cms
class MediaForm(forms.ModelForm):
    file = forms.FileField()

    class Meta:
        model = Media
        # Don't show the date created field because we want that to be set automatically
        exclude = ('date_created', 'content',)

I'm sure I tried that before but it appears to have fixed my issue, hopefully this might help someone else who runs into the same problem.

我确定我之前尝试过,但它似乎解决了我的问题,希望这可能会帮助遇到同样问题的其他人。

#1


2  

I eventually solved this by moving the FileField from my Model into my ModelForm like so:

我最终通过将FileField从我的模型移动到我的ModelForm中来解决这个问题:

# Used for uploading media that forms part of a story
class Media(models.Model):
    title = models.CharField(max_length=100)
    type = models.CharField(max_length=5, choices=MEDIA_TYPES)
    content = models.TextField()
    date_created = models.DateTimeField(auto_now_add=True)

# Used to convert the media model to a form in the cms
class MediaForm(forms.ModelForm):
    file = forms.FileField()

    class Meta:
        model = Media
        # Don't show the date created field because we want that to be set automatically
        exclude = ('date_created', 'content',)

I'm sure I tried that before but it appears to have fixed my issue, hopefully this might help someone else who runs into the same problem.

我确定我之前尝试过,但它似乎解决了我的问题,希望这可能会帮助遇到同样问题的其他人。