102 lines
3.3 KiB
Python
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)
|