Skip to content

Instantly share code, notes, and snippets.

@peketamin
Last active May 3, 2020 11:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peketamin/2c5316a1cd21d6f78023830e160724ed to your computer and use it in GitHub Desktop.
Save peketamin/2c5316a1cd21d6f78023830e160724ed to your computer and use it in GitHub Desktop.
Django: Create ImageField thumbnail
from pathlib import PosixPath
from django import forms
from django.conf import settings
from django.contrib import admin
from my_app.models import Item
class ItemForm(forms.ModelForm):
logo_name = forms.CharField(
widget=forms.HiddenInput(),
required=False,
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.logo:
self.fields["logo_name"].initial = self.instance.logo.name
class Meta:
model = Item
class ItemAdmin(admin.ModelAdmin):
def response_change(self, request, obj):
"""Delete logo file when clear-checkbox is on."""
if request.POST.get("logo-clear") == "on":
# settings.MEDIA_ROOT: pathlib.PosixPath
logo_file = settings.MEDIA_ROOT / request.POST["logo_name"]
logo_file.unlink(missing_ok=True)
return super().response_change(request, obj)
from io import BytesIO
from pathlib import PurePath
from typing import NamedTuple
from uuid import uuid4
from PIL import Image
from django.core.files import File
from django.db import models
class ImageSize(NamedTuple):
height: int = 150
width: int = 150
def logo_upload_path(instance, filename):
"""For logo."""
if instance.logo and instance.logo.name.startswith("item_thumbnails/"):
return instance.logo.name
filename_p = PurePath(filename)
return f"item_thumbnails/{uuid4().hex}{filename_p.suffix}"
class Item(models.Model):
logo = models.ImageField("logo", blank=True, default=None)
THUMBNAIL_SIZE = ImageSize(height=150, width=150)
def _create_thumbnail(self):
if not self.logo:
return
if self.logo.height <= self.THUMBNAIL_SIZE.height and self.logo.width <= self.THUMBNAIL_SIZE.width:
return
self.logo.open()
logo_buf = BytesIO(self.logo.read())
self.logo.close()
image = Image.open(logo_buf)
image.thumbnail(self.THUMBNAIL_SIZE, Image.ANTIALIAS)
thumbnail_buf = BytesIO()
image.save(thumbnail_buf, image.format)
thumbnail_buf.seek(0)
file = File(thumbnail_buf, name=logo_upload_path(self, self.logo.name))
self.logo.file = file
self.logo.name = file.name
def save(self, *args, **kwargs):
self._create_thumbnail()
super().save(*args, **kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment