django中admin页上传图片控件

效果是这样的,就是想再django自带的admin管理页中,添加新项的时候有个图片上传的控件按钮

124350_OREp_1463495.png

storage.py:

#-*- coding: UTF-8 -*-
from os import environ

debug = not environ.get("APP_NAME", "")                                                               #判断sae环境
from django.utils.translation import ugettext as _
from django.core.files.storage import FileSystemStorage
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.conf import settings
import time,os,uuid,random,unicodedata,StringIO
from django.core.files.base import ContentFile
if not debug:
    import sae
    import tempfile
    import sae.storage
    from PIL import Image                     #这里是关键,sae加载Image的方式
else:
    import Image


class SaeAndNotSaeStorage(FileSystemStorage):
    """
    这是一个支持sae和本地django的FileStorage基类
    修改存储文件的路径和基本url
    """
    def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL):
        super(SaeAndNotSaeStorage, self).__init__(location, base_url)

    def get_valid_name(self, name):
        """
        这个方法用于验证文件名,我这里的处理方法是去掉中文,我没有找到支持中文名的方法,欢迎补充
        """
        #name = unicodedata.normalize('NFKD', name).encode('ascii', 'ignore')
        #处理中文文件名sae不支持
        if not debug:
            try:
                if 1:
                    #去掉中文
                    name = unicodedata.normalize('NFKD', name).encode('ascii', 'ignore')
                else:
                    for k in name:
                        if self.is_chinese(k):
                            name = "wszw%s"%random.randint(0,100)
            except Exception,e:
                name = "%s.jpg"%type(name)
        #end
        return super(SaeAndNotSaeStorage, self).get_valid_name(name)

    @property
    def maxsize(self):
        return 10*1024*1024#文件2M--sae限制只能传2M,单个文件,据说是10M,其实只有2M

    @property
    def filetypes(self):
        return []

    def makename(self,name):
        #取一个不重复的名字,sae会把重名覆盖
        oname = os.path.basename(name)
        path = os.path.dirname(name)
        #首先判断是否需要重命名---也就是说不想改名字的就加这个前缀
        if oname.find("_mine_")==0:
            oname = oname.replace("_mine_","")
            name = os.path.join(path, oname)
            return name
        #end---首先判断是否需要重命名
        try:
            fname, hk = oname.split(".")
        except Exception,e:
            fname, hk = oname, ''
        if hk:
            rname  = "%s_%s.%s"%(random.randint(0,10000), fname,hk)
        else:
            rname  = "%s_%s"%(random.randint(0,10000), fname)
        name = os.path.join(path, rname)
        #end
        return name

    def _save(self, name, content):
        """
        可以判断上传哪些文件
        """
        hz = name.split(".")[-1]
        #类型判断
        if self.filetypes!='*':
            if hz.lower() not in self.filetypes:
                raise SuspiciousOperation(u"不支持的文件类型,支持%s"%self.filetypes)
        #end
        name = self.makename(name)
        #大小判断
        if content.size > self.maxsize:
            raise SuspiciousOperation(u"文件大小超过限制")
        #end
        #保存
        if not debug:
            s = sae.storage.Client()
            if hasattr(content, '_get_file'):#admin入口
                ob = sae.storage.Object(content._get_file().read())
            else:#view入口(ContentFile)
                ob = sae.storage.Object(content.read())
            url =s.put('image', name, ob)   #注意这里的media,是sae-storage上的domain名
            return name
        else:
            return super(SaeAndNotSaeStorage, self)._save(name, content)
        #end--保存

    def delete(self,name):
        """
       sae的存储空间很宝贵,所有我们在删除图片数据库记录的时候也需要删除图片
        """
        if not debug:
            s = sae.storage.Client()
            try:
                s.delete('image', name)
            except Exception,e:
                pass
        else:
            super(SaeAndNotSaeStorage, self).delete(name)

class ImageStorage(SaeAndNotSaeStorage):
    """
    实现一个ImageField的Storage
    """
    @property
    def maxsize(self):
        return 2*1024*1024#文件2M

    @property
    def filetypes(self):
        return ['jpg','jpeg','png','gif']

class FileStorage(SaeAndNotSaeStorage):
    @property
    def maxsize(self):
        return 10*1024*1024#文件5M

    @property
    def filetypes(self):
        return "*"

    #def makename(self, name):
    #    return name


class ThumbStorage(ImageStorage):
    """
    缩略图-------这个非常关键,处理后的图片在sae上怎么保存,关键就在StringIO
    """ 
    def _save(self, name, content):
        #处理
        image = Image.open(content)
        image = image.convert('RGB')
        image.thumbnail((50, 50), Image.ANTIALIAS)

        output = StringIO.StringIO()
        image.save(output,'JPEG')
        co = ContentFile(output.getvalue())
        output.close()
        #end
        return super(ThumbStorage, self)._save(name, co)

调用的model.py:

from storage import ImageStorage,FileStorage,ThumbStorage

iconUrl = models.ImageField(upload_to=upload_path_handler, storage=ImageStorage(),verbose_name="图片地址")


转载于:https://my.oschina.net/iq19900204/blog/482719

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值