Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing Images In DB Using Django Models

I am using Django for creating one Web service and I want that web service to return Images. I am deciding the basic architecture of my Web service. What I came up to conclusion after stumbling on google is:

  1. I should store Images in DB after encoding them to Base64 format.
  2. Transferring the Images would be easy when directly Bases64 decoded string is transmitted.

But I have one issue how can I store bases64 encoded string in DB using Django models? Also, if you see any flaw in my basic architecture please guide me.

I am new to Web services and Django

Thanks!!

like image 607
Mayank Jain Avatar asked Sep 11 '13 17:09

Mayank Jain


People also ask

Can DB store images?

A database gives you the opportunity to store photos and other small images in a database table. You can create such a database table for example when you want to create an online photo album with descriptions of your photos. Storing images in a database table is not recommended.

How does Django store data in database?

Creating objects To create an object, instantiate it using keyword arguments to the model class, then call save() to save it to the database. This performs an INSERT SQL statement behind the scenes. Django doesn't hit the database until you explicitly call save() . The save() method has no return value.

How do I store images in Django?

In Django, a default database is automatically created for you. All you have to do is add the tables called models. The upload_to tells Django to store the photo in a directory called pics under the media directory. The list_display list tells Django admin to display its contents in the admin dashboard.

Is it better to store images in database or filesystem?

Generally databases are best for data and the file system is best for files. It depends what you're planning to do with the image though. If you're storing images for a web page then it's best to store them as a file on the server. The web server will very quickly find an image file and send it to a visitor.


1 Answers

Some people states that using DB for storing images is not a good idea but that's no true. My advice is to use Django with AppEngine Blobstore Service in this way:

First, create a Django Custom Storage (or pick one from someone else like this one):

from django.core.files.storage import Storage 

class AppEngineBlobStorage(Storage):

    def exists(self, name):
       ...   

    def size(self, name):
       ...

    def url(self, name):
       ...

    def delete(self, name):
       ...

    def listdir(self, path):
       raise NotImplementedError()

This custom storage can receive Django images, convert them to Base64 strings and send them to your AppEngine Blobstore Service application (via xmlrpc for example).

Then, create a Django Image model:

from django.db import models
from django.db.models.fields.files import ImageField
from .storage import AppEngineBlobStorage

class Photo(models.Model):
    caption = models.CharField(max_length=64, blank=True)
    blob = ImageField(
        upload_to='BlobStorage',
        storage=AppEngineBlobStorage(),
        max_length=255,
        blank=False,
    )
    serving_url = models.URLField()
    ...

Then, you have to create an AppEngine application for receiving Django requests for storing images, transform Base64 strings to raw and store them in a Blob. For example:

# coding=utf-8

from __future__ import with_statement

import webapp2

from base64 import b64decode
from StringIO import StringIO
from xmlrpcserver import XmlRpcServer

from google.appengine.api import files
from google.appengine.api import images
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers


class ImageRpcServer(object):

    def upload(self, meta, photo, mime_type):
        data = b64decode(photo)
        file_name = files.blobstore.create(mime_type=mime_type)
        with files.open(file_name, 'a') as f:
            f.write(data)
        files.finalize(file_name)
        key = files.blobstore.get_blob_key(file_name)
        return str(key)

    def serving_url(self, meta, key):
        return images.get_serving_url(blobstore.BlobKey(key))

      ...

Serving a blob

The key is the function get_serving_url. From Google docs:

If you are serving images, a more efficient and potentially less-expensive method is to use get_serving_url using the App Engine Images API rather than send_blob. The get_serving_url function lets you serve the image directly, without having to go through your App Engine instances.

Finally, by serving images with AppEngine, you can use the awesome feature of resize and crop images (check the documentation of get_serving_url function), for example:

// Resize the image to 32 pixels (aspect-ratio preserved) http://your_app_id.appspot.com/randomStringImageId=s32

Hope it helps. Good luck!

like image 93
Cartucho Avatar answered Oct 18 '22 03:10

Cartucho