文档章节

django中admin页上传图片控件

余成海
 余成海
发布于 2015/07/23 12:39
字数 740
阅读 136
收藏 1

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

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="图片地址")


© 著作权归作者所有

下一篇: ios隐性动画
余成海
粉丝 62
博文 57
码字总数 29577
作品 0
杭州
iOS工程师
私信 提问
加载中

评论(2)

余成海
余成海 博主

引用来自“lrqrun”的评论

怎么写到django了, 海神。。。

哎呦,强哥,好久不见,都是瞎写的
lrqrun
lrqrun
怎么写到django了, 海神。。。
如何用Django分页器实现文章分页?

1、概述 Django有自带的分页器,可以将数据分在不同的页面中,并提供一些属性和方法实现对分页数据的操作。分页功能的类位于django/core/paginator.py中。 2、数据准备 在具体实现分类器功能...

mcyJacky的博客
2017/12/11
0
0
[旧]使用DjangoUeditor在django中进行富文本开发

Django的安装和生成项目这里不介绍了。 DjangoUeditor下载地址:https://github.com/zhangfisher/DjangoUeditor 使用python setup.py install 安装, 推荐使用pip install DjangoUeditor安装...

子夜闻雪
2015/03/11
502
0
你应该使用 Django admin 的 9 个理由

本文源自 Reddit 上对我最近的一个帖子的评论: “问题是,我问到的每个人都持反对意见,他们认为 admin 只限于超级用户,很不灵活并且是难以定制。” —来自 Reddit 的 andybak 我现在要澄清...

有来有趣
2015/12/10
11.9K
24
Django 开源相册组件介绍 django-photologue

一、安装与使用体验 在线体验地址:http://www.django-photologue.net/ 下载地址:https://github.com/jdriscoll/django-photologue 下载之后的安装: 解压文件包-找到setup.py所在文件路径,...

xiaoge2016
2018/04/05
170
0
Python3基础之学习笔记(十五)-Ajax-文件上传-图片验证码

1. Django 1.1 Ajax 1.1.1 Ajax简介 AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,...

GoldenKitten
01/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

golang-字符串-地址分析

demo package mainimport "fmt"func main() {str := "map.baidu.com"fmt.Println(&str, str)str = str[0:5]fmt.Println(&str, str)str = "abc"fmt.Println(&s......

李琼涛
今天
4
0
Spring Boot WebFlux 增删改查完整实战 demo

03:WebFlux Web CRUD 实践 前言 上一篇基于功能性端点去创建一个简单服务,实现了 Hello 。这一篇用 Spring Boot WebFlux 的注解控制层技术创建一个 CRUD WebFlux 应用,让开发更方便。这里...

泥瓦匠BYSocket
今天
6
0
从0开始学FreeRTOS-(列表与列表项)-3

FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像。 在FreeRTOS中,列表与列表项使用得非常多,是FreeRTOS的一个数...

杰杰1号
今天
4
0
Java反射

Java 反射 反射是框架设计的灵魂(使用的前提条件:必须先得到代表的字节码的 Class,Class 类 用于表示.class 文件(字节码)) 一、反射的概述 定义:JAVA 反射机制是在运行状态中,对于任...

zzz1122334
今天
5
0
聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部