ref: use thumbnail image instead of size limit
This commit is contained in:
@@ -69,7 +69,7 @@ class Migration(migrations.Migration):
|
||||
('sort', models.IntegerField(default=0, verbose_name='Sortierung')),
|
||||
('isExtended', models.BooleanField(verbose_name='Bis 1.1.2025 verstecken')),
|
||||
('title', models.CharField(max_length=100, verbose_name='Titel')),
|
||||
('image', common.form.img_with_preview.FileWithImagePreview(blank=True, null=True, upload_to=app.models.place.overwrite_img_upload, verbose_name='Bild')),
|
||||
('image', common.form.img_with_preview.ThumbnailImageField(blank=True, null=True, upload_to=app.models.place.overwrite_img_upload, verbose_name='Bild')),
|
||||
('audio', common.form.audio_file.AudioFileField(blank=True, null=True, upload_to=app.models.place.overwrite_audio_upload, verbose_name='Audio')),
|
||||
('location', map_location.fields.LocationField(blank=True, null=True, verbose_name='Position')),
|
||||
('description', tinymce.models.HTMLField(verbose_name='Beschreibung')),
|
||||
|
||||
@@ -13,7 +13,7 @@ from map_location.fields import LocationField
|
||||
|
||||
from app.models.category import Category
|
||||
from common.form.audio_file import AudioFileField
|
||||
from common.form.img_with_preview import FileWithImagePreview
|
||||
from common.form.img_with_preview import ThumbnailImageField
|
||||
|
||||
|
||||
def overwrite_img_upload(instance: 'Place', filename: str):
|
||||
@@ -38,8 +38,8 @@ class Place(models.Model):
|
||||
sort = models.IntegerField('Sortierung', default=0)
|
||||
isExtended = models.BooleanField('Bis 1.1.2025 verstecken')
|
||||
title = models.CharField('Titel', max_length=100)
|
||||
image = FileWithImagePreview('Bild', blank=True, null=True,
|
||||
upload_to=overwrite_img_upload)
|
||||
image = ThumbnailImageField('Bild', blank=True, null=True,
|
||||
upload_to=overwrite_img_upload) # type: ignore
|
||||
audio = AudioFileField('Audio', blank=True, null=True,
|
||||
upload_to=overwrite_audio_upload)
|
||||
location = LocationField('Position', blank=True, null=True, options={
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.admin.widgets import AdminFileWidget
|
||||
from django.core.validators import FileExtensionValidator
|
||||
from django.core.files.uploadedfile import UploadedFile
|
||||
from django.db import models
|
||||
from django.forms import FileInput, widgets
|
||||
from django.forms import widgets
|
||||
|
||||
from common.validators import MaxFilesizeValidator, readableToInt
|
||||
from PIL import Image, ImageOps
|
||||
|
||||
MAX_UPLOAD_SIZE = '312 KB'
|
||||
|
||||
def makeThumnail(data: UploadedFile, size: 'tuple[int, int]'):
|
||||
with Image.open(data) as img:
|
||||
ImageOps.exif_transpose(img, in_place=True)
|
||||
img.thumbnail(size)
|
||||
if img.mode != 'RGB':
|
||||
img = img.convert('RGB')
|
||||
data.seek(0)
|
||||
data.truncate()
|
||||
img.save(data, 'jpeg')
|
||||
|
||||
|
||||
class ImageFileWidget(widgets.ClearableFileInput):
|
||||
@@ -19,38 +26,19 @@ class ImageFileWidget(widgets.ClearableFileInput):
|
||||
return context
|
||||
|
||||
|
||||
class ImgField(forms.FileField):
|
||||
widget = ImageFileWidget
|
||||
default_validators = [
|
||||
FileExtensionValidator(['jpg', 'jpeg', 'png']),
|
||||
MaxFilesizeValidator(MAX_UPLOAD_SIZE),
|
||||
]
|
||||
|
||||
def widget_attrs(self, widget):
|
||||
attrs = super().widget_attrs(widget)
|
||||
if isinstance(widget, FileInput) and 'accept' not in widget.attrs:
|
||||
attrs.setdefault('accept', 'image/png,image/jpeg') # image/*
|
||||
if isinstance(widget, ImageFileWidget):
|
||||
attrs.update({
|
||||
'data-upload-limit': readableToInt(MAX_UPLOAD_SIZE),
|
||||
'data-upload-limit-str': MAX_UPLOAD_SIZE,
|
||||
'onchange': 'validate_upload_limit(this)',
|
||||
})
|
||||
return attrs
|
||||
|
||||
|
||||
class FileWithImagePreview(models.FileField): # use ImageField to omit Pillow
|
||||
class ThumbnailImageField(models.ImageField):
|
||||
__del_image_on_save = False
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
if kwargs['widget'] is AdminFileWidget:
|
||||
# Override admin widget. Defined by ImgField anyway
|
||||
del kwargs['widget']
|
||||
return super().formfield(**{'form_class': ImgField, **kwargs})
|
||||
kwargs['widget'] = ImageFileWidget
|
||||
return super().formfield(**kwargs)
|
||||
|
||||
def save_form_data(self, instance, data):
|
||||
if data is False:
|
||||
self.__del_image_on_save = True
|
||||
if isinstance(data, UploadedFile):
|
||||
makeThumnail(data, (1200, 900)) # only on create
|
||||
# on update: django.db.models.fields.files.ImageFieldFile
|
||||
super().save_form_data(instance, data)
|
||||
|
||||
def pre_save(self, model_instance, add):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Django==4.2.13
|
||||
Django>=4.2,<5
|
||||
Pillow==10.4.0
|
||||
django_colorfield==0.11.0
|
||||
django-tinymce==4.1.0
|
||||
|
||||
Reference in New Issue
Block a user