This commit is contained in:
Irwan Cahyono 2025-07-09 05:26:59 +07:00
parent b50cded82f
commit 53fd650b4f
5 changed files with 44 additions and 6 deletions

View File

@ -3,14 +3,15 @@ from django_softdelete.models import SoftDeleteModel
class Character(SoftDeleteModel): class Character(SoftDeleteModel):
class CharacterType(models.TextChoices): CHARACTER_TYPE_CHOICES = [
HUMAN = 'HUMAN', 'Manusia' ('manusia', 'Manusia'),
ANIMAL = 'ANIMAL', 'Hewan' ('hewan', 'Hewan'),
]
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
description = models.TextField(blank=True, null=True) description = models.TextField(blank=True, null=True)
sex = models.BooleanField(blank=False, null=False) sex = models.BooleanField(blank=False, null=False)
type = models.CharField(max_length=25, choices=CharacterType.choices, default=CharacterType.HUMAN) type = models.CharField(max_length=25, choices=CHARACTER_TYPE_CHOICES)
featured_image = models.CharField(max_length=1000) featured_image = models.CharField(max_length=1000)
featured_icon = models.CharField(max_length=1000) featured_icon = models.CharField(max_length=1000)

View File

@ -20,6 +20,10 @@ def validate_image(image):
except Exception: except Exception:
raise ValidationError("Invalid image file.") raise ValidationError("Invalid image file.")
def validate_file_size(image):
if image.size > 10 * 1024 * 1024:
raise ValidationError("File size exceeds 10MB.")
class Content(SoftDeleteModel): class Content(SoftDeleteModel):
CONTENT_THEME_CHOICES = [ CONTENT_THEME_CHOICES = [
@ -114,3 +118,15 @@ class Content(SoftDeleteModel):
def __str__(self): def __str__(self):
return self.title return self.title
class Media(SoftDeleteModel):
name = models.CharField(max_length=255, null=False)
media = models.FileField(
max_length=255,
upload_to="uploads/medias/",
validators=[validate_file_size],
null=False, blank=False)
def __str__(self):
return self.name

View File

@ -1,4 +1,4 @@
from django.forms import ImageField from django.forms import ImageField, FileField
from rest_framework import serializers from rest_framework import serializers
from content import models from content import models
@ -28,3 +28,10 @@ class ContentDetailSerializer(serializers.ModelSerializer):
raise serializers.ValidationError({'topic': f'Topic "{topic}" is not valid for theme "{theme}"'}) raise serializers.ValidationError({'topic': f'Topic "{topic}" is not valid for theme "{theme}"'})
return data return data
class ContentMediaSerializer(serializers.ModelSerializer):
media = FileField(max_length=255, allow_empty_file=False)
class Meta:
model = models.Media
fields = ['id', 'name', 'media']

View File

@ -8,4 +8,7 @@ urlpatterns = [
path('themes/', views.ContentThemeChoices.as_view()), path('themes/', views.ContentThemeChoices.as_view()),
path('topics/<str:theme_key>/', views.ContentTopicChoices.as_view()), path('topics/<str:theme_key>/', views.ContentTopicChoices.as_view()),
path('formats/', views.ContentFormatChoices.as_view()), path('formats/', views.ContentFormatChoices.as_view()),
path('media/', views.ContentMediaList.as_view()),
path('media/<int:pk>/', views.ContentMediaDetail.as_view()),
] ]

View File

@ -85,3 +85,14 @@ class ContentFormatChoices(views.APIView):
for choice in models.Content.CONTENT_FORMAT_CHOICES for choice in models.Content.CONTENT_FORMAT_CHOICES
] ]
}) })
class ContentMediaList(generics.ListCreateAPIView):
queryset = models.Media.objects.all()
serializer_class = serializers.ContentMediaSerializer
class ContentMediaDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = models.Media.objects.all()
serializer_class = serializers.ContentMediaSerializer
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
search_fields = ['name']
ordering_fields = '__all__'