Add image upload support
Images can be uploaded, thumbnails are created, they're displayed within the threads themselves. Just like four chans! There is not an upload size limit set yet. Gotta get on that next. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,8 +1,42 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
from django.db import models
|
||||
from django.db.models.signals import post_save
|
||||
from django.db.models import signals
|
||||
from django.conf import settings
|
||||
from django.core.files.base import ContentFile
|
||||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from PIL import Image
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
def image_upload(instance, filename):
|
||||
op_id = instance.op.id if instance.op else instance.id
|
||||
now = timezone.now()
|
||||
now_sec = now.strftime("%s.%f")
|
||||
ext = Path(filename).suffix.lower()
|
||||
if ext in (".jpeg", ".jpg"):
|
||||
ext = ".jpg"
|
||||
|
||||
if ext not in (".jpg", ".png", ".gif"):
|
||||
raise Exception("File type invalid")
|
||||
|
||||
if instance.op:
|
||||
return f"{instance.board.url}/{instance.op.id}/{now_sec}{ext}"
|
||||
else:
|
||||
return f"{instance.board.url}/{now_sec}{ext}"
|
||||
|
||||
|
||||
def thumbs_upload(instance, filename):
|
||||
op_id = instance.op.id if instance.op else instance.id
|
||||
now = timezone.now()
|
||||
now_sec = now.strftime("%s.%f")
|
||||
ext = Path(filename).suffix.lower()
|
||||
if instance.op:
|
||||
return f"{instance.board.url}/{instance.op.id}/{now_sec}{ext}"
|
||||
else:
|
||||
return f"{instance.board.url}/{now_sec}t{ext}"
|
||||
|
||||
|
||||
class Board(models.Model):
|
||||
@@ -39,8 +73,52 @@ class Post(models.Model):
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
# Last bump time
|
||||
last_bump = models.DateTimeField(auto_now_add=True)
|
||||
# Image
|
||||
image = models.ImageField(
|
||||
upload_to=image_upload,
|
||||
null=True,
|
||||
blank=True,
|
||||
width_field="image_width",
|
||||
height_field="image_height",
|
||||
)
|
||||
# Thumbnail
|
||||
thumbnail = models.ImageField(upload_to=thumbs_upload, editable=False, null=True)
|
||||
# Original image name
|
||||
original_image_name = models.CharField(max_length=255, null=True)
|
||||
# Image width and height
|
||||
image_width = models.IntegerField(null=True)
|
||||
image_height = models.IntegerField(null=True)
|
||||
|
||||
# TODO : images
|
||||
def save(self, *args, **kwargs):
|
||||
if self.image:
|
||||
self.original_image_name = self.image.name
|
||||
self.__make_thumbnail()
|
||||
super(Post, self).save(*args, **kwargs)
|
||||
|
||||
def __make_thumbnail(self):
|
||||
image = Image.open(self.image)
|
||||
image.thumbnail(settings.THUMB_SIZE, Image.ANTIALIAS)
|
||||
|
||||
image_path = Path(self.image.name)
|
||||
thumb_path = Path(image_path.stem + "t" + image_path.suffix)
|
||||
|
||||
ext = thumb_path.suffix.lower()
|
||||
if ext in (".jpg", ".jpeg"):
|
||||
FTYPE = "JPEG"
|
||||
elif ext == ".gif":
|
||||
FTYPE = "GIF"
|
||||
elif ext == ".png":
|
||||
FTYPE = "PNG"
|
||||
else:
|
||||
raise Exception("File type invalid")
|
||||
|
||||
thumb_temp = BytesIO()
|
||||
image.save(thumb_temp, FTYPE)
|
||||
thumb_temp.seek(0)
|
||||
|
||||
# save=False stops recursion
|
||||
self.thumbnail.save(thumb_path, ContentFile(thumb_temp.read()), save=False)
|
||||
thumb_temp.close()
|
||||
|
||||
def get_absolute_url(self):
|
||||
if self.op is None:
|
||||
@@ -57,8 +135,16 @@ class Post(models.Model):
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_save, sender=Post)
|
||||
@receiver(signals.post_save, sender=Post)
|
||||
def post_created(sender, instance, created, **kwargs):
|
||||
if created and instance.op:
|
||||
instance.op.last_bump = timezone.now()
|
||||
instance.op.save()
|
||||
|
||||
|
||||
@receiver(signals.post_delete, sender=Post)
|
||||
def post_deleted(sender, instance, **kwargs):
|
||||
if instance.image and Path(instance.image.path).is_file():
|
||||
os.remove(instance.image.path)
|
||||
if instance.thumbnail and Path(instance.thumbnail.path).is_file():
|
||||
os.remove(instance.thumbnail.path)
|
||||
|
||||
Reference in New Issue
Block a user