My problem revolves around a user making a text file upload to my app. I need to get this file and process it with my app before saving it to the datastore. From the little I have read, I understand that user uploads go directly to the datastore as blobs, which is ok if I could then get that file, perform operations on it(meaning change data inside) and then re-write it back to the datastore. All these operations need to be done by the app.
Unfortunately from the datastore documenation, http://code.google.com/appengine/docs/python/blobstore/overview.html
an app cannot directly create a blob in the datastore. That's my main headache. I simply need a way of creating a new blob/file in the datastore from my app without any user upload interaction.
blobstore != datastore.
You can read and write data to the datastore as much as you like so long as your data is <1MB using a db.BlobProperty on your entity.
As Wooble comments, the new File API lets you write to the blobstore, but unless you are incrementally writting to the blobstore-file using tasks or something like the mapreduce library you are still limited by the 1MB API call limit for reading/writing.
Thanks for your help. After many sleepless nights, 3 App Engine Books and A LOT of Googling, I've found the answer. Here is the code (it should be pretty self explanatory):
from __future__ import with_statement
from google.appengine.api import files
from google.appengine.ext import blobstore
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler):
def get(self):
self.response.out.write('Hello WOrld')
form=''' <form action="/" method="POST" enctype="multipart/form-data">
Upload File:<input type="file" name="file"><br/>
<input type="submit"></form>'''
self.response.out.write(form)
blob_key="w0MC_7MnZ6DyZFvGjgdgrg=="
blob_info=blobstore.BlobInfo.get(blob_key)
start=0
end=blobstore.MAX_BLOB_FETCH_SIZE-1
read_content=blobstore.fetch_data(blob_key, start, end)
self.response.out.write(read_content)
def post(self):
self.response.out.write('Posting...')
content=self.request.get('file')
#self.response.out.write(content)
#print content
file_name=files.blobstore.create(mime_type='application/octet-stream')
with files.open(file_name, 'a') as f:
f.write(content)
files.finalize(file_name)
blob_key=files.blobstore.get_blob_key(file_name)
print "Blob Key="
print blob_key
def main():
application=webapp.WSGIApplication([('/', MainHandler)],debug=True)
util.run_wsgi_app(application)
if __name__=='__main__':
main()
Related
I have a Entity with ~50k rows in Google Cloud Datastore, the stand alone not GAE. I am starting development with GAE and would like to query this existing datastore without having to import it to GAE. I have been unable to find a way to connect to an existing datastore Kind.
Basic code altered from Hello World and other guides im trying to get working as a POC.
import webapp2
import json
import time
from google.appengine.ext import ndb
class Product(ndb.Model):
type = ndb.StringProperty()
#classmethod
def query_product(cls):
return ndb.gql("SELECT * FROM Product where name >= :a LIMIT 5 ")
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
query = Product.query_product()
self.response.write(query)
app = webapp2.WSGIApplication([
('/', MainPage),
], debug=True)
Returned Errors are
TypeError: Model Product has no property named 'name'
Seems obvious that its trying to use a GAE datastore with the kind Product instead of my existing Datastore with Product already defined, But I cant find how to make that connection.
There is only one Google Cloud Datastore. App Engine does not have a datastore of its own - it works with the same Google Cloud Datastore.
All entities in the Datastore are stored for a particular project. If you are trying to access data from a different project, you will not be able to see it without going through special authentication.
I'm not too certain what it is you're trying to accomplish when you say that you would like to query this existing datastore without having to import it to GAE. I'm guessing that you have project A with the datastore with 50k rows, and you're starting project B. And you want to access the project A datastore from project B. If this is the case, and if you're trying to access the datastore from a different project, then maybe this previous answer that mentions remote api can help you.
Below is working code. I was pretty close at the time I made this original post but the reason I was getting no data back was because I was running my App locally. As soon as I actually deployed my code to App Engine it pulled from Datastore no problem.
import webapp2
import json
import time
from google.appengine.datastore.datastore_query import Cursor
from google.appengine.ext import ndb
class Product(ndb.Model):
name = ndb.StringProperty()
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
query = ndb.gql("SELECT * FROM Product where name >= 'a' LIMIT 5 ")
output = query.fetch()
#query = Product.query(Product.name == 'zubo - pre-owned - nintendo ds')
#query = Product.query()
#output = query.fetch(10)
self.response.write(output)
app = webapp2.WSGIApplication([
('/', MainPage),
], debug=True)
I'm trying to access data that ODK has pushed into the datastore. The below code words fine when I query an entity that I created via Python, which was called "ProductSalesData". The entity name ODK has given it's data is "opendatakit.test1". When I update the data model to class opendatakit.test1(db.Model) it obviously bombs due to a sytax error. How do I call that data?
#!/usr/bin/env python
import webapp2
from google.appengine.ext import db
class ProductSalesData(db.Model):
product_id = db.IntegerProperty()
date = db.DateTimeProperty()
store = db.StringProperty()
q = ProductSalesData.all()
class simplequery(webapp2.RequestHandler):
def get(self):
for ProductSalesData in q:
self.response.out.write('Result:%s<br />' % ProductSalesData.store)
app = webapp2.WSGIApplication(
[('/', simplequery)],
debug=True)
I know you tagged GAE, but do you have to access it straight through the datastore?
If not, I've had better success using the API that has already been built into aggregate: https://code.google.com/p/opendatakit/wiki/BriefcaseAggregateAPI
If you need GAE access I'd suggest the ODK developers group over on google groups - they're pretty active.
I am building a blog site in Google App Engine, using django-nonrel and I need a way to store and display images in blog posts etc.
The idea is to have an upload application to upload images for specific articles etc, and then use an absolute or relative URL for the imd src.
I am using django-filetransfers to upload the images (http://www.allbuttonspressed.com/projects/django-filetransfers).
Questions are:
1) Is anyone using Google App Engine and django-nonrel to host their blog? If so how and where are you storing images? Is using GAE Blobstore for this use an overkill?
2) For image URL I am using the download path as set up in flie-transfers application. eg.
Is this correct? Seems a bit weird not to reference using .png extension or anything. But this might be the way to reference images from the blobstore?
Still learning the rope with Django and Google App Engine so any help would be really appreciated.
Thanks
Can,
I have had a similar experience in using the Blobstore with Django-nonrel.
For your first question, the Blobstore is not overkill and I think is in fact the only way you can upload an image without updating your whole project and republishing it. GAE does not let you write to a directory because of the server's high replication and security. It's a trade off with being able to spin up all the servers automatically as demand increase. If you try to do anything that involves writing to a directory, App Engine will error.
I am looking for a better solution to your second question myself. I would like to be able to reference the file by name myself. The key I think will be adding an extra attribute to the "Upload" Model that gets set to the filename at save time. I have not tried it but it should work.
Update:
This worked.
Here is the Model:
class UploadModel(models.Model):
title = models.CharField(max_length=64, blank=True)
file = models.FileField(upload_to='uploads/%Y/%m/%d/%H/%M/%S/')
filename = models.CharField(max_length=100, editable=False, null=True, blank=True)
def save(self, *args, **kwargs):
self.filename = self.file.name.rsplit('/', 1)[-1]
super(UploadModel, self).save(*args, **kwargs)
here is the download handler:
def download_handler(request, filename):
upload = get_object_or_404(UploadModel, filename=filename)
return serve_file(request, upload.file, save_as=True)
the URL mapping:
url(r'^file/(?P<filename>.+)$', 'cms.views.download_handler_filename', name='cms-download_file'),
Once you do this you can access the file by filename (This is just a snippet from the example app). As you can see the 'pk' was replaced with the 'filename' attribute:
{% url cms-download_file filename=upload.filename as fallback_url %}
<p><img src="{% firstof upload.file|public_download_url fallback_url %}"></p>
What I am stuck on myself is getting 'public_download_url' to work with GAE Blobstore. If someone else can comment in with how to get a proper public backed to work that automatically generates the public URL I would greatly appreciate it.
Grant
I have a csv file and I'd need to get it into a list object in app inventor.
I'm not sure if there is a better / simpler method, but I've looked at the following methods and I'm not really sure the best route.
Also I'm using python but I could switch to use java app engine.
Google Fusion Tables (gft)
Google Docs & TinyGSdb
App Engine & Python
Down in the comments there is an example on how to update the app.yaml to include some code to parse a csv file.
import csv
reader = csv.reader(open(‘efile_newestSFO_8354d71d-e3fb-4864-b9bf-5312a89e24d7_2010.csv’,”rU”), delimiter=’,')
for row in reader:
print row[0],row[1]
I'd rather not go out to the web every time the app loads to retrieve the list.
Thoughts?
You can write a handler to let you upload the cvs to BlobStore, then use BlobStore APIs from your app to read the file.
That approach is well-described here (in Java, but the same idea applies to Python).
Can the Blobstore in GWT/GAE be used as a database? Or is a new Blobstore created each time I launch the application? I would like to store information without losing it when the application is closed. But I can't seem to find a way to name a Blobstore and then reference it by its ID. Thanks!
If all you want to do is store a string I'd still suggest using the datastore.
Here's the complete python source to an App Engine app that retrieves, modifies, and stores some text in the datastore:
from google.appengine.ext import webapp, db
from google.appengine.ext.webapp import util
class TextDoc(db.Model):
text = db.TextProperty(default="")
class MainHandler(webapp.RequestHandler):
def get(self):
my_text_doc = TextDoc.get_or_insert('my_text_doc')
my_text_doc.text += "Blah, blah, blah. "
my_text_doc.put()
self.response.out.write(my_text_doc.text)
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
If you're working in Java it would be more verbose, but similar.