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')),
|
('sort', models.IntegerField(default=0, verbose_name='Sortierung')),
|
||||||
('isExtended', models.BooleanField(verbose_name='Bis 1.1.2025 verstecken')),
|
('isExtended', models.BooleanField(verbose_name='Bis 1.1.2025 verstecken')),
|
||||||
('title', models.CharField(max_length=100, verbose_name='Titel')),
|
('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')),
|
('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')),
|
('location', map_location.fields.LocationField(blank=True, null=True, verbose_name='Position')),
|
||||||
('description', tinymce.models.HTMLField(verbose_name='Beschreibung')),
|
('description', tinymce.models.HTMLField(verbose_name='Beschreibung')),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from map_location.fields import LocationField
|
|||||||
|
|
||||||
from app.models.category import Category
|
from app.models.category import Category
|
||||||
from common.form.audio_file import AudioFileField
|
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):
|
def overwrite_img_upload(instance: 'Place', filename: str):
|
||||||
@@ -38,8 +38,8 @@ class Place(models.Model):
|
|||||||
sort = models.IntegerField('Sortierung', default=0)
|
sort = models.IntegerField('Sortierung', default=0)
|
||||||
isExtended = models.BooleanField('Bis 1.1.2025 verstecken')
|
isExtended = models.BooleanField('Bis 1.1.2025 verstecken')
|
||||||
title = models.CharField('Titel', max_length=100)
|
title = models.CharField('Titel', max_length=100)
|
||||||
image = FileWithImagePreview('Bild', blank=True, null=True,
|
image = ThumbnailImageField('Bild', blank=True, null=True,
|
||||||
upload_to=overwrite_img_upload)
|
upload_to=overwrite_img_upload) # type: ignore
|
||||||
audio = AudioFileField('Audio', blank=True, null=True,
|
audio = AudioFileField('Audio', blank=True, null=True,
|
||||||
upload_to=overwrite_audio_upload)
|
upload_to=overwrite_audio_upload)
|
||||||
location = LocationField('Position', blank=True, null=True, options={
|
location = LocationField('Position', blank=True, null=True, options={
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
from django import forms
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.admin.widgets import AdminFileWidget
|
from django.core.files.uploadedfile import UploadedFile
|
||||||
from django.core.validators import FileExtensionValidator
|
|
||||||
from django.db import models
|
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):
|
class ImageFileWidget(widgets.ClearableFileInput):
|
||||||
@@ -19,38 +26,19 @@ class ImageFileWidget(widgets.ClearableFileInput):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class ImgField(forms.FileField):
|
class ThumbnailImageField(models.ImageField):
|
||||||
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
|
|
||||||
__del_image_on_save = False
|
__del_image_on_save = False
|
||||||
|
|
||||||
def formfield(self, **kwargs):
|
def formfield(self, **kwargs):
|
||||||
if kwargs['widget'] is AdminFileWidget:
|
kwargs['widget'] = ImageFileWidget
|
||||||
# Override admin widget. Defined by ImgField anyway
|
return super().formfield(**kwargs)
|
||||||
del kwargs['widget']
|
|
||||||
return super().formfield(**{'form_class': ImgField, **kwargs})
|
|
||||||
|
|
||||||
def save_form_data(self, instance, data):
|
def save_form_data(self, instance, data):
|
||||||
if data is False:
|
if data is False:
|
||||||
self.__del_image_on_save = True
|
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)
|
super().save_form_data(instance, data)
|
||||||
|
|
||||||
def pre_save(self, model_instance, add):
|
def pre_save(self, model_instance, add):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Django==4.2.13
|
Django>=4.2,<5
|
||||||
Pillow==10.4.0
|
Pillow==10.4.0
|
||||||
django_colorfield==0.11.0
|
django_colorfield==0.11.0
|
||||||
django-tinymce==4.1.0
|
django-tinymce==4.1.0
|
||||||
|
|||||||
Reference in New Issue
Block a user