resize изображения при сохранении

Как я могу легко resize изображения после его загрузки в Django? Я использую Django 1.0.2, и я установил PIL.

Я думал об переопределении метода save () модели, чтобы изменить его размер, но я действительно не знаю, как начать и переопределить его.

Может ли кто-нибудь указать мне в правильном направлении? Благодаря 🙂

@ Guðmundur H: Это не сработает, потому что пакет django-stdimage не работает на Windows 🙁

Вы должны использовать метод обработки загруженного файла, как показано в документации Django .

В этом методе вы можете объединить куски в переменной (а не записывать их непосредственно на диск), создать изображение PIL из этой переменной, resize изображения и сохранить его на диске.

В PIL вы должны посмотреть Image.fromstring и Image.resize .

Я рекомендую использовать StdImageField из django-stdimage , он должен обрабатывать всю грязную работу за вас. Он прост в использовании, вы просто указываете размеры измененного изображения в определении поля:

 class MyModel(models.Model): image = StdImageField(upload_to='path/to/img', size=(640, 480)) 

Проверьте документы – он также может создавать миниатюры.

Я использую этот код для обработки загруженных изображений, изменения размера их в памяти (без сохранения их навсегда на диске), а затем сохранения большого пальца на Django ImageField. Надежда может помочь.

  def handle_uploaded_image(i): import StringIO from PIL import Image, ImageOps import os from django.core.files import File # read image from InMemoryUploadedFile image_str = “” for c in i.chunks(): image_str += c # create PIL Image instance imagefile = StringIO.StringIO(image_str) image = Image.open(imagefile) # if not RGB, convert if image.mode not in (“L”, “RGB”): image = image.convert(“RGB”) #define file output dimensions (ex 60x60) x = 130 y = 130 #get orginal image ratio img_ratio = float(image.size[0]) / image.size[1] # resize but constrain proportions? if x==0.0: x = y * img_ratio elif y==0.0: y = x / img_ratio # output file ratio resize_ratio = float(x) / y x = int(x); y = int(y) # get output with and height to do the first crop if(img_ratio > resize_ratio): output_width = x * image.size[1] / y output_height = image.size[1] originX = image.size[0] / 2 - output_width / 2 originY = 0 else: output_width = image.size[0] output_height = y * image.size[0] / x originX = 0 originY = image.size[1] / 2 - output_height / 2 #crop cropBox = (originX, originY, originX + output_width, originY + output_height) image = image.crop(cropBox) # resize (doing a thumb) image.thumbnail([x, y], Image.ANTIALIAS) # re-initialize imageFile and set a hash (unique filename) imagefile = StringIO.StringIO() filename = hashlib.md5(imagefile.getvalue()).hexdigest()+'.jpg' #save to disk imagefile = open(os.path.join('/tmp',filename), 'w') image.save(imagefile,'JPEG', quality=90) imagefile = open(os.path.join('/tmp',filename), 'r') content = File(imagefile) return (filename, content) #views.py form = YourModelForm(request.POST, request.FILES, instance=profile) if form.is_valid(): ob = form.save(commit=False) try: t = handle_uploaded_image(request.FILES['icon']) ob.image.save(t[0],t[1]) except KeyError: ob.save() 

Я настоятельно рекомендую приложение для сортировки миниатюр для упрощения и прозрачной обработки изображений. Это происходит в каждом проекте Django, который я запускаю.

Я знаю, что это устарело, но для кого-то наткнулся на него, есть пакет, django-thumbs на Django-thumbs – Легкие мощные миниатюры для Django, интегрированные с StorageBackend , которые автоматически генерируют миниатюры в размерах, которые вы указываете, или нет, т. Затем вы вызываете миниатюру, которую хотите, с необходимыми размерами.

Например, если вы хотите, чтобы изображение имело миниатюры 64×64 и 128×128, вы просто импортируете thumbs.models.ImageWithThumbsField и используете его вместо ImageField . Добавьте значения параметров sizes=((64,64),(128,128)) в определение поля, затем из вашего шаблона вы можете позвонить:

 {{ ClassName.field_name.url_64x64 }} 

а также

 {{ ClassName.field_name.url_128x128 }} 

для отображения эскизов. Вуаля! Вся работа выполняется в этом пакете для вас.

Вот полное решение для ya с использованием формы. Я использовал для этого admin просмотров:

 class MyInventoryItemForm(forms.ModelForm): class Meta: model = InventoryItem exclude = ['thumbnail', 'price', 'active'] def clean_photo(self): import StringIO image_field = self.cleaned_data['photo'] photo_new = StringIO.StringIO(image_field.read()) try: from PIL import Image, ImageOps except ImportError: import Image import ImageOps image = Image.open(photo_new) # ImageOps compatible mode if image.mode not in ("L", "RGB"): image = image.convert("RGB") image.thumbnail((200, 200), Image.ANTIALIAS) image_file = StringIO.StringIO() image.save(image_file, 'png') image_field.file = image_file return image_field 

Моя модель инвентаря выглядит следующим образом:

 class InventoryItem(models.Model): class Meta: ordering = ['name'] verbose_name_plural = "Items" def get_absolute_url(self): return "/products/{0}/".format(self.slug) def get_file_path(instance, filename): if InventoryItem.objects.filter(pk=instance.pk): cur_inventory = InventoryItem.objects.get(pk=instance.pk) if cur_inventory.photo: old_filename = str(cur_inventory.photo) os.remove(os.path.join(MEDIA_ROOT, old_filename)) ext = filename.split('.')[-1] filename = "{0}.{1}".format(uuid.uuid4(), ext) return os.path.join('inventory', filename) #return os.path.join(filename) def admin_image(self): return ''.format(MEDIA_URL, self.photo) admin_image.allow_tags = True photo = models.ImageField(_('Image'), upload_to=get_file_path, storage=fs, blank=False, null=False) thumbnail = models.ImageField(_('Thumbnail'), upload_to="thumbnails/", storage=fs, blank=True, null=True) 

….

Я закончил перезаписывать функцию сохранения модели вместо этого, чтобы сохранить фотографию и большой палец, а не просто resize фотографии:

 def save(self): # Save this photo instance first super(InventoryItem, self).save() from PIL import Image from cStringIO import StringIO from django.core.files.uploadedfile import SimpleUploadedFile # Set our max thumbnail size in a tuple (max width, max height) THUMBNAIL_SIZE = (200, 200) # Open original photo which we want to thumbnail using PIL's Image object image = Image.open(os.path.join(MEDIA_ROOT, self.photo.name)) if image.mode not in ('L', 'RGB'): image = image.convert('RGB') image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS) # Save the thumbnail temp_handle = StringIO() image.save(temp_handle, 'png') # image stored to stringIO temp_handle.seek(0) # sets position of file to 0 # Save to the thumbnail field suf = SimpleUploadedFile(os.path.split(self.photo.name)[-1], temp_handle.read(), content_type='image/png') # reads in the file to save it self.thumbnail.save(suf.name+'.png', suf, save=False) #Save this photo instance again to save the thumbnail super(InventoryItem, self).save() 

Оба работают отлично, хотя в зависимости от того, что вы хотите сделать 🙂

  • Выпадающее меню Страна / Штат / Город внутри встроенного администратора Django
  • пользовательские сообщения об ошибках с формой модели
  • Группировка CheckboxSelectMultiple в шаблоне Django
  • Несколько classов форм в джинго общих (classных) представлениях
  • Давайте будем гением компьютера.