Last active
May 3, 2020 11:04
-
-
Save peketamin/2c5316a1cd21d6f78023830e160724ed to your computer and use it in GitHub Desktop.
Django: Create ImageField thumbnail
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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