Files
freekake_api/freekake_api/entertainment/models.py
T
2025-08-06 13:34:02 +07:00

102 lines
3.3 KiB
Python

from django.db import models
from django.core.exceptions import ValidationError
from django_softdelete.models import SoftDeleteModel
from PIL import Image
def validate_image_size(image):
if image.size > 1 * 1024 * 1024:
raise ValidationError("File size exceeds 1MB.")
def validate_image_ext(image):
allowed_extensions = ['png', 'jpg', 'jpeg']
ext = image.name.split('.')[-1].lower()
if ext not in allowed_extensions:
raise ValidationError("Invalid file type. Only PNG or JPEG allowed.")
def validate_image(image):
try:
img = Image.open(image)
img.verify()
except Exception:
raise ValidationError("Invalid image file.")
def validate_file_size(image):
if image.size > 1 * 1024 * 1024:
raise ValidationError("File size exceeds 1MB.")
class Manga(SoftDeleteModel):
MANGA_GENRE_CHOICES = [
('komedi','Komedi'),
('petualangan', 'Petualangan'),
('fiksi-ilmiah', 'Fiksi Ilmiah'),
('fantasi', 'Fantasi'),
('slice-of-life', 'Kehidupan Sehari-hari'),
]
MANGA_STATUS_CHOICES = [
('draft', 'Draf'),
('published', 'Dipublikasikan'),
('archived', 'Diarsipkan'),
]
title = models.CharField(max_length=255, null=False)
slug = models.SlugField(max_length=255, unique=True)
featured_image = models.ImageField(
max_length=255,
upload_to="uploads/entertainments/",
validators=[validate_image_size, validate_image_ext, validate_image],
null=False, blank=False)
genre = models.CharField(max_length=50, choices=MANGA_GENRE_CHOICES)
synopsis = models.CharField(max_length=1000, null=True, blank=True)
coin = models.IntegerField()
color = models.CharField(max_length=7, null=True, blank=True)
status = models.CharField(max_length=50, choices=MANGA_STATUS_CHOICES, default='draft')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
posted_at = models.DateTimeField(null=True, blank=True)
archived_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
class MangaChapter(SoftDeleteModel):
manga = models.ForeignKey(Manga, related_name='chapters', on_delete=models.CASCADE)
chapter = models.PositiveSmallIntegerField(null=False)
status = models.CharField(max_length=50, choices=Manga.MANGA_STATUS_CHOICES, default='draft')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
posted_at = models.DateTimeField(null=True, blank=True)
archived_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.manga.title + " - Chapter: " + str(self.chapter)
class MangaChapterPage(SoftDeleteModel):
chapter = models.ForeignKey(MangaChapter, related_name='media', on_delete=models.CASCADE)
order = models.PositiveSmallIntegerField(null=False)
media = models.FileField(
max_length=255,
upload_to="uploads/entertainments/manga/chapters/media/",
validators=[validate_file_size],
null=False, blank=False)
def __str__(self):
return self.chapter.manga.title + " - Chapter: " + self.chapter.chapter + " - Page: " + str(self.order)