In a nutshell, we are trying to implement the following example from Google using Django:
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
class MainHandler(webapp2.RequestHandler):
def get(self):
upload_url = blobstore.create_upload_url('/upload')
self.response.out.write('<html><body>')
self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
self.response.out.write("""Upload File: <input type="file" name="file"><br> <input type="submit"
name="submit" value="Submit"> </form></body></html>""")
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file') # 'file' is file upload field in the form
blob_info = upload_files[0]
self.redirect('/serve/%s' % blob_info.key())
Our app is written in Django 1.x. We use urls.py, views.py and models.py to define our url scheme, views and data models respectively.
In our database, we need to keep track of the data file (or at least, a reference to where the file exists on disk). Currently, our data model is as follows:
class FileData(models.Model):
token = models.CharField(max_length=10)
file = models.FileField(upload_to=get_upload_file_name, null=True, default=None, blank=True)
The field 'token' contains a token that client apps will use to request the file for download. The field 'file' is intended to contain the data. However, if we need to make it a reference to a blob location, it won't be a problem. We just don't know what to do at this point. What is the right solution?
Our urls pattern is as follows:
urlpatterns = patterns('',
url(r'^upload/', 'views.upload', name='upload'),
url(r'^/serve/([^/]+)?', 'views.servehandler', name='servehandler'),
)
Our form is as follows.
class DataUploadForm(forms.Form):
"""
FileData form
"""
token = forms.CharField(max_length=10)
file = forms.FileField()
class Meta:
model = FileData
fields = ['token', 'file', ]
def __init__(self, *args, **kwargs):
super(DataUploadForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout(
'token',
'file',
ButtonHolder(
Submit('submit', 'Submit', css_class='btn btn-success btn-block'),
),
)
Our view is as follows.
def upload(request):
args = {}
args.update(csrf(request))
if request.method == 'POST':
print "In /upload"
form = DataUploadForm(request.POST, request.FILES)
if form.is_valid():
file_data = FileData()
file_data.token = request.POST.get('token')
file_data.file = request.FILES.get('file')
print "===========> Uploading:" + file_data.token
file_data.save()
return render(request, 'upload_success.html', args)
form = DataUploadForm()
args['form'] = form
return render(request, 'upload.html', args)
When we execute, we get:
Exception Value:
[Errno 30] Read-only file system: u
What are we doing wrong? How can we improve our code? How do we get Google App Engine to save our file, perhaps in the blobstore, and give us the reference to where the file exists for use in downloading it later?
Please be complete. Describe changes needed for urls.py, models.Model, views.py and yaml files (if necessary). Address how to upload large files (i.e., files greater than 40 MB each).
Please don't send us any more links. We have searched and seen a lot of postings-- none of which answers this question. If you can, please post a code snippets that answer the question -- not links.