使用Django模型在DB中存储图像

时间:2013-09-11 17:34:16

标签: python database django

我正在使用Django创建一个Web服务,我希望该Web服务返回Images。我正在决定我的Web服务的基本架构。我在谷歌上磕磕绊绊之后得出的结论是:

  1. 我应该在将图像编码为Base64格式后将图像存储在数据库中。
  2. 直接传输Bases64解码字符串时,传输图像会很容易。
  3. 但我有一个问题,如何使用Django模型在base中存储base64编码的字符串?另外,如果您发现我的基本架构存在任何缺陷,请指导我。

    我是Web服务和Django的新手

    谢谢!

2 个答案:

答案 0 :(得分:9)

有些人说使用数据库存储图像并不是一个好主意,但事实并非如此。我的建议是以这种方式将Django与AppEngine Blobstore Service一起使用:

首先,创建一个Django Custom Storage(或从其他人那里选择一个,如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()

此自定义存储可以接收Django映像,将它们转换为Base64字符串并将它们发送到AppEngine Blobstore Service应用程序(例如,通过xmlrpc)。

然后,创建一个Django Image模型:

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()
    ...

然后,您必须创建一个AppEngine应用程序来接收存储图像的Django请求,将Base64字符串转换为raw并将它们存储在Blob中。例如:

# 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))

      ...

提供blob

关键是函数get_serving_url。来自Google文档:

  

如果您正在提供图像,则效率更高且可能更高   更便宜的方法是使用App Engine使用get_serving_url   Images API而不是send_blob。 get_serving_url函数允许   您可以直接提供图像,而无需通过您的应用程序   引擎实例。

最后,通过使用AppEngine提供图像,您可以使用调整大小和裁剪图像的强大功能(查看get_serving_url函数的文档),例如:

  

//将图像大小调整为32像素(保留纵横比)   http://your_app_id.appspot.com/randomStringImageId=s32

希望它有所帮助。祝你好运!

答案 1 :(得分:0)

您可以将图像存储在 bytea字段中。

bytea数据类型允许存储二进制字符串。 Postgres Documentation Link

早期版本的Django不支持bytea字段,所以我一直在使用这个名为djorm-ext-pgbytea的库: