Question

I'm creating an ecommerce platform on Google App Engine using Python. For that, I need to store the details of the products I will be offering in a separate entity, which will also include an image of every individual product. Now, how do I store images in the datastore? Also, more importantly, how do I extract images from the database and display it for the user on my application?

EDIT:

After uploading my image into an 'Images' entity, I was trying to display it. Here's the code for the same:

main.py

class FileUpload(Handler):
    def post(self):
        file_upload = self.request.POST.get("file", None)
        file_name = file_upload.filename
        image = Images(id=file_name, file_name=file_name, blob=file_upload.file.read())
        image.put()

        self.response.headers[b'Content-Type'] = mimetypes.guess_type(image.file_name)[0]
        self.response.write(image.blob)
        self.final()

    def final(self):
        images = db.GqlQuery("Select * FROM Images WHERE file_name = 'CN.jpg'")
        self.render("template.html", images = images)

class Blob(Handler):
    def get(self):
        self.render("blob.html")


app = webapp2.WSGIApplication([('/', MainPage),
                                ('/signup', Register),
                                ('/login', Login),
                                ('/logout', Logout),
                                ('/mp', MP),
                                (r'/file_upload', FileUpload),
                                ('/blob', Blob)], debug=True)

template.html

<html>
<head>
    <title>Template</title>
</head>
<body>
    {%
        for image in images
    %}
    <div>{{image.blob}}</div>
    {%endfor%}
</body>
</html>

blob.html

<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Image Upload</title>
</head>
<body>
<form action="/file_upload" enctype="multipart/form-data" method="post">
    <div><input type="file" name="file"/></div>
    <div><input type="submit" value="Upload"></div>
</form>
</body>
</html>

Now, in template.html, I was expecting the image I was trying to extract to be displayed. However, I get the following error:

<div>{{image.blob}}</div>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)
Was it helpful?

Solution

A basic example of uploading an image, saving it in the datastore and serving the image.

fileupload.py:

import webapp2
from google.appengine.ext import ndb
import mimetypes


class Images(ndb.Model):
    file_name = ndb.StringProperty()
    blob = ndb.BlobProperty()


class FileUpload(webapp2.RequestHandler):

    def post(self):

        file_upload = self.request.POST.get("file", None)
        file_name = file_upload.filename
        image = Images(id=file_name, file_name=file_name, blob=file_upload.file.read())
        image.put()

        self.response.headers[b'Content-Type'] = mimetypes.guess_type(image.file_name)[0]
        self.response.write(image.blob)


class ImgServe(webapp2.Requesthandler):

    def get(self, resource):

        image = ndb.Key('Images', resource).get()
        self.response.headers[b'Content-Type'] = mimetypes.guess_type(image.file_name)[0]
        self.response.write(image.blob)            

Here is the static form to post the image:

<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Image Upload</title>
</head>
<body>
<form action="/file_upload" enctype="multipart/form-data" method="post">
    <div><input type="file" name="file"/></div>
    <div><input type="submit" value="Upload"></div>
</form>
</body>
</html>

Routing the form post:

webapp2.Route(r'/file_upload', handler='fileupload.FileUpload')

Routing for the image server: <img alt="test" src="/img_serve/test.png" />

webapp2.Route(r'/img_serve/<resource:(.*)>', handler='fileupload.ImgServe'))

OTHER TIPS

You can use Google High Performance Image Serving. You have to store or upload your images to the blobstore or Google Cloud Storage and create a serving_url.

The benefits:

  • high performance
  • Google will serve the images. You do not need a handler;
  • cheap
  • dynamic resizing and cropping.

More: Serving a blob in : https://developers.google.com/appengine/docs/python/blobstore/ get_serving_url : https://developers.google.com/appengine/docs/python/images/functions

There are several options, which you can decide between based upon the size of image and the workflow.

  1. If the images are fixed and are only changed by the development team, you could include them as static files.
  2. You can use the blobstore api to enable uploading and viewing of images.
  3. You can use Google Cloud Storage libraries for uploading/viewing too. I get the impression that Google is moving toward this rather than the blobstore.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top