2015-08-20 71 views
0

我有一个应用程序,用于存储上传的文件(图像,zip,视频..等)。 我使用模型FileField来处理上传。上传图像时,我想调整图像大小并将其保存在模型中的其他字段(缩略图)中。如何调整图像大小并保存它 - django

这里是我的models.py

class Files(models.Model): 
    file = models.FileField(upload_to=upload_path()) 
    thumb = models.CharField(max_length=255,default=None,blank=True , null=True) 
    user = models.ForeignKey(User, null=True,blank=True) 
    date = models.DateTimeField('date added',blank=True, null=True) 

文件是存储原始文件的URL,以及拇指是存储缩略图URL。

我知道我们可以使用PIL来调整大小,但我是python的新手,我不知道如何使用它并将它保存在应用程序中。

+0

你为什么不使用和imagefield? –

+0

您可以轻松调整大小。 –

+0

@appa_lover,因为我需要上传其他文件。 –

回答

0

这是我为烧瓶应用程序网站编写的模块,但您可以将它更改为Django应用程序并使用它。它创建缩略图和裁剪图像。对我很有用:

""" 
usage: <img src="{{ thumbnail('files/'+media.path, '150x150') }}" alt="" /> 
""" 

# python imports 
import os 
import errno 
import traceback 

try: 
    from PIL import Image, ImageOps 
except ImportError: 
    raise RuntimeError('Image module of PIL needs to be installed') 


class Thumbnail(object): 

    def __init__(self, app=None): 
     if app is not None: 
      self.init_app(self.app) 
     else: 
      self.app = None 

    def init_app(self, app): 
     self.app = app 

     if not self.app.config.get('MEDIA_FOLDER', None): 
      raise RuntimeError('You\'re using the flask-thumbnail app ' 
           'without having set the required MEDIA_FOLDER setting.') 

     if not self.app.config.get('THUMBNAIL_FOLDER', None): 
      raise RuntimeError(
       'You didn\'t set THUMBNAIL_FOLDER setting.') 

     app.config.setdefault('THUMBNAIL_FOLDER', os.path.join(self.app.config['MEDIA_FOLDER'], 'thumbnail')) 
     app.config.setdefault('MEDIA_URL', '/media/') 
     app.config.setdefault('THUMBNAIL_URL', os.path.join(self.app.config['MEDIA_URL'], 'thumbnail')) 

     app.jinja_env.globals['thumbnail'] = self.thumbnail 

    def thumbnail(self, img_url, size, crop=None, bg=None, quality=92): 
     """ 

     :param img_url: url img - '/assets/media/summer.jpg' 
     :param size: size return thumb - '100x100' 
     :param crop: crop return thumb - 'fit' or None 
     :param bg: tuple color or None - (255, 255, 255, 0) 
     :param quality: JPEG quality 1-100 
     :return: :thumb_url: 
     """ 
     try: 
      width, height = [int(x) for x in size.split('x')] 
      url_path, img_name = os.path.split(img_url) 
      name, fm = os.path.splitext(img_name) 

      miniature = self._get_name(name, fm, size, crop, bg, quality) 

      original_filename = os.path.join(
       self.app.config['MEDIA_FOLDER'], 
       url_path, 
       img_name) 
      thumb_filename = os.path.join(
       self.app.config['THUMBNAIL_FOLDER'], 
       miniature) 

      # create folders 
      self._get_path(thumb_filename) 

      thumb_url = os.path.join(
       self.app.config['THUMBNAIL_URL'], 
       miniature) 

      if os.path.exists(thumb_filename): 
       return thumb_url 

      elif not os.path.exists(thumb_filename): 
       thumb_size = (width, height) 
       try: 
        image = Image.open(original_filename) 
       except IOError: 
        return None 

       if crop == 'fit': 
        img = ImageOps.fit(image, thumb_size, Image.ANTIALIAS) 
       else: 
        img = image.copy() 
        img.thumbnail((width, height), Image.ANTIALIAS) 

       if bg: 
        img = self._bg_square(img, bg) 

       img.save(thumb_filename, image.format, quality=quality) 

       return thumb_url 
     except Exception, e: 
      traceback.print_exc() 
      print(e.message) 

    @staticmethod 
    def _bg_square(img, color=0xff): 
     size = (max(img.size),) * 2 
     layer = Image.new('L', size, color) 
     layer.paste(
      img, tuple(map(lambda x: (x[0] - x[1])/2, zip(size, img.size)))) 
     return layer 

    @staticmethod 
    def _get_path(full_path): 
     directory = os.path.dirname(full_path) 

     try: 
      if not os.path.exists(full_path): 
       os.makedirs(directory) 
     except OSError as e: 
      if e.errno != errno.EEXIST: 
       raise 

    @staticmethod 
    def _get_name(name, fm, *args): 
     for v in args: 
      if v: 
       name += '_%s' % v 
     name += fm 

     return name 
0

这就是我如何使它工作。

from django.core.files.uploadedfile import InMemoryUploadedFile 

def create_thumbnail(obj, ext=None): 
    imaged, imgformat = resize_and_crop(obj.file, (150, 150),crop_type='middle') 
    thumb_io = BytesIO() 
    imaged.save(thumb_io, format=imgformat, quality=92) 
    new_file_name = u'thumb-' + str(obj.file.name) 
    thumbfile = InMemoryUploadedFile(thumb_io, 
          u"thumb", # important to specify field name here 
          new_file_name, 
          ext, 
          thumb_io, 
          None) 
    return thumbfile 

class Files(models.Model): 
    file = models.FileField(upload_to=upload_path()) 
    thumb = models.FileField(max_length=255,default=None,blank=True , null=True) 
    user = models.ForeignKey(User, null=True,blank=True) 
    date = models.DateTimeField('date added',blank=True, null=True) 

    def save(self, *args, **kwargs): 
     self.url = create_thumbnail(self, ext)  
     return super(MediaUpload, self).save(*args, **kwargs) 

resize_and_crop()是指此excellent script

这里的要点是使用InMemoryUploadedFile将文件保存在内存中,并将其传递给FileField以完成剩余的工作。

相关问题