penambahan field content
This commit is contained in:
parent
e91f2bfbdf
commit
cd593b8e5c
@ -27,6 +27,15 @@ class CharacterSkinSerializer(serializers.ModelSerializer):
|
|||||||
model = models.CharacterSkin
|
model = models.CharacterSkin
|
||||||
fields = ['id', 'name', 'description', 'featured_image', 'featured_icon', 'character']
|
fields = ['id', 'name', 'description', 'featured_image', 'featured_icon', 'character']
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
request_method = self.context.get('request').method if self.context.get('request') else None
|
||||||
|
|
||||||
|
if request_method in ['PUT', 'PATCH']:
|
||||||
|
# Jadikan optional di update
|
||||||
|
self.fields['featured_image'].required = False
|
||||||
|
self.fields['featured_icon'].required = False
|
||||||
|
|
||||||
class CharacterSkinDetailSerializer(serializers.ModelSerializer):
|
class CharacterSkinDetailSerializer(serializers.ModelSerializer):
|
||||||
character = CharacterSerializer(read_only=True)
|
character = CharacterSerializer(read_only=True)
|
||||||
featured_image = ImageField(max_length=255, allow_empty_file=False)
|
featured_image = ImageField(max_length=255, allow_empty_file=False)
|
||||||
|
|||||||
@ -21,8 +21,8 @@ def validate_image(image):
|
|||||||
raise ValidationError("Invalid image file.")
|
raise ValidationError("Invalid image file.")
|
||||||
|
|
||||||
def validate_file_size(image):
|
def validate_file_size(image):
|
||||||
if image.size > 10 * 1024 * 1024:
|
if image.size > 1 * 1024 * 1024:
|
||||||
raise ValidationError("File size exceeds 10MB.")
|
raise ValidationError("File size exceeds 1MB.")
|
||||||
|
|
||||||
class Content(SoftDeleteModel):
|
class Content(SoftDeleteModel):
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class Content(SoftDeleteModel):
|
|||||||
('olahraga', 'Olahraga'),
|
('olahraga', 'Olahraga'),
|
||||||
('waktu-tidur', 'Waktu Tidur'),
|
('waktu-tidur', 'Waktu Tidur'),
|
||||||
('kesehatan-mental', 'Kesehatan Mental'),
|
('kesehatan-mental', 'Kesehatan Mental'),
|
||||||
('pendidikan-seksua', 'Pendidikan Seksual'),
|
('pendidikan-seksual', 'Pendidikan Seksual'),
|
||||||
('rokok-alkohol-narkoba', 'Bahaya Merokok dan Alkohol serta Pencegahan Narkoba'),
|
('rokok-alkohol-narkoba', 'Bahaya Merokok dan Alkohol serta Pencegahan Narkoba'),
|
||||||
('sistem-imun', 'Sistem Imun')
|
('sistem-imun', 'Sistem Imun')
|
||||||
],
|
],
|
||||||
@ -69,7 +69,7 @@ class Content(SoftDeleteModel):
|
|||||||
],
|
],
|
||||||
'keselamatan': [
|
'keselamatan': [
|
||||||
('lalu-lintas', 'Keselamatan Berlalu Lintas'),
|
('lalu-lintas', 'Keselamatan Berlalu Lintas'),
|
||||||
('pertolongan-pertama', 'Pertolongan Petrtama'),
|
('pertolongan-pertama', 'Pertolongan Pertama'),
|
||||||
('bencana', 'Kesiapsiagaan Bencana')
|
('bencana', 'Kesiapsiagaan Bencana')
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -87,10 +87,22 @@ class Content(SoftDeleteModel):
|
|||||||
('personality-quiz', 'Permainan Tebak Sifat'),
|
('personality-quiz', 'Permainan Tebak Sifat'),
|
||||||
('game-map', 'Peta Permainan'),
|
('game-map', 'Peta Permainan'),
|
||||||
('pilihan-ganda', 'Pilihan Ganda'),
|
('pilihan-ganda', 'Pilihan Ganda'),
|
||||||
|
('augmented-reality', 'Augmented Reality'),
|
||||||
|
]
|
||||||
|
|
||||||
|
CONTENT_TYPE_CHOICES = [
|
||||||
|
('content','Konten'),
|
||||||
|
('advertorial', 'Advertorial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
CONTENT_STATUS_CHOICES = [
|
||||||
|
('draft', 'Draf'),
|
||||||
|
('published', 'Dipublikasikan'),
|
||||||
|
('archived', 'Diarsipkan'),
|
||||||
]
|
]
|
||||||
|
|
||||||
title = models.CharField(max_length=255, null=False)
|
title = models.CharField(max_length=255, null=False)
|
||||||
slug = models.SlugField(max_length=255)
|
slug = models.SlugField(max_length=255, unique=True)
|
||||||
|
|
||||||
featured_image = models.ImageField(
|
featured_image = models.ImageField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
@ -98,24 +110,30 @@ class Content(SoftDeleteModel):
|
|||||||
validators=[validate_image_size, validate_image_ext, validate_image],
|
validators=[validate_image_size, validate_image_ext, validate_image],
|
||||||
null=False, blank=False)
|
null=False, blank=False)
|
||||||
|
|
||||||
theme = models.CharField(max_length=25, choices=CONTENT_THEME_CHOICES)
|
theme = models.CharField(max_length=50, choices=CONTENT_THEME_CHOICES)
|
||||||
topic = models.CharField(max_length=25)
|
topic = models.CharField(max_length=50)
|
||||||
format = models.CharField(max_length=25, choices=CONTENT_FORMAT_CHOICES)
|
format = models.CharField(max_length=50, choices=CONTENT_FORMAT_CHOICES)
|
||||||
|
|
||||||
description = models.CharField(max_length=255, null=True, blank=True)
|
description = models.CharField(max_length=255, null=True, blank=True)
|
||||||
content = models.TextField(null=True)
|
content = models.TextField(null=True)
|
||||||
data = models.JSONField(null=True)
|
data = models.JSONField(null=True)
|
||||||
|
|
||||||
grades = models.JSONField(null=True)
|
grades = models.JSONField(null=True, blank=True)
|
||||||
|
|
||||||
point = models.IntegerField()
|
point = models.IntegerField()
|
||||||
coin = models.IntegerField()
|
coin = models.IntegerField()
|
||||||
|
|
||||||
color = models.CharField(max_length=7, null=True, blank=True)
|
color = models.CharField(max_length=7, null=True, blank=True)
|
||||||
|
|
||||||
|
type = models.CharField(max_length=50, choices=CONTENT_TYPE_CHOICES, default='content')
|
||||||
|
status = models.CharField(max_length=50, choices=CONTENT_STATUS_CHOICES, default='draft')
|
||||||
|
|
||||||
created_at = models.DateTimeField(auto_now_add=True)
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
updated_at = models.DateTimeField(auto_now=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):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
@ -124,7 +142,7 @@ class Media(SoftDeleteModel):
|
|||||||
name = models.CharField(max_length=255, null=False)
|
name = models.CharField(max_length=255, null=False)
|
||||||
media = models.FileField(
|
media = models.FileField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
upload_to="uploads/medias/",
|
upload_to="uploads/media/",
|
||||||
validators=[validate_file_size],
|
validators=[validate_file_size],
|
||||||
null=False, blank=False)
|
null=False, blank=False)
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,69 @@ class ContentSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Content
|
model = models.Content
|
||||||
fields = ['id', 'title', 'slug', 'featured_image', 'theme', 'topic', 'format', 'description','content', 'point', 'coin', 'data', 'grades', 'color']
|
fields = [
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
'slug',
|
||||||
|
'featured_image',
|
||||||
|
'theme',
|
||||||
|
'topic',
|
||||||
|
'format',
|
||||||
|
'description',
|
||||||
|
'content',
|
||||||
|
'point',
|
||||||
|
'coin',
|
||||||
|
'data',
|
||||||
|
'grades',
|
||||||
|
'color',
|
||||||
|
'type',
|
||||||
|
'status',
|
||||||
|
'posted_at',
|
||||||
|
'archived_at',
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
request_method = self.context.get('request').method if self.context.get('request') else None
|
||||||
|
|
||||||
|
if request_method in ['PUT', 'PATCH']:
|
||||||
|
self.fields['featured_image'].required = False
|
||||||
|
|
||||||
class ContentDetailSerializer(serializers.ModelSerializer):
|
class ContentDetailSerializer(serializers.ModelSerializer):
|
||||||
featured_image = ImageField(max_length=255, allow_empty_file=False)
|
featured_image = ImageField(max_length=255, allow_empty_file=False)
|
||||||
|
theme_display = serializers.SerializerMethodField()
|
||||||
|
topic_display = serializers.SerializerMethodField()
|
||||||
|
format_display = serializers.SerializerMethodField()
|
||||||
|
type_display = serializers.SerializerMethodField()
|
||||||
|
status_display = serializers.SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Content
|
model = models.Content
|
||||||
fields = ['id', 'title', 'slug', 'featured_image', 'theme', 'topic', 'format', 'description','content', 'point', 'coin', 'data', 'grades', 'color']
|
fields = [
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
'slug',
|
||||||
|
'featured_image',
|
||||||
|
'theme',
|
||||||
|
'topic',
|
||||||
|
'format',
|
||||||
|
'description',
|
||||||
|
'content',
|
||||||
|
'point',
|
||||||
|
'coin',
|
||||||
|
'data',
|
||||||
|
'grades',
|
||||||
|
'color',
|
||||||
|
'type',
|
||||||
|
'status',
|
||||||
|
'posted_at',
|
||||||
|
'archived_at',
|
||||||
|
'theme_display',
|
||||||
|
'topic_display',
|
||||||
|
'format_display',
|
||||||
|
'type_display',
|
||||||
|
'status_display',
|
||||||
|
]
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
theme = data.get('theme')
|
theme = data.get('theme')
|
||||||
@ -29,6 +84,25 @@ class ContentDetailSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_theme_display(self, obj):
|
||||||
|
return dict(models.Content.CONTENT_THEME_CHOICES).get(obj.theme)
|
||||||
|
|
||||||
|
def get_topic_display(self, obj):
|
||||||
|
# Ambil label topic dari dict berdasarkan theme
|
||||||
|
topic_choices = dict(models.Content.CONTENT_TOPIC_CHOICES).get(obj.theme, [])
|
||||||
|
topic_dict = dict(topic_choices)
|
||||||
|
return topic_dict.get(obj.topic)
|
||||||
|
|
||||||
|
def get_format_display(self, obj):
|
||||||
|
return dict(models.Content.CONTENT_FORMAT_CHOICES).get(obj.format, obj.format)
|
||||||
|
|
||||||
|
def get_type_display(self, obj):
|
||||||
|
return dict(models.Content.CONTENT_TYPE_CHOICES).get(obj.type, obj.type)
|
||||||
|
|
||||||
|
def get_status_display(self, obj):
|
||||||
|
return dict(models.Content.CONTENT_STATUS_CHOICES).get(obj.status, obj.status)
|
||||||
|
|
||||||
|
|
||||||
class ContentMediaSerializer(serializers.ModelSerializer):
|
class ContentMediaSerializer(serializers.ModelSerializer):
|
||||||
media = FileField(max_length=255, allow_empty_file=False)
|
media = FileField(max_length=255, allow_empty_file=False)
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,8 @@ 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('types/', views.ContentTypeChoices.as_view()),
|
||||||
|
path('statuses/', views.ContentStatusChoices.as_view()),
|
||||||
|
|
||||||
path('media/', views.ContentMediaList.as_view()),
|
path('media/', views.ContentMediaList.as_view()),
|
||||||
path('media/<int:pk>/', views.ContentMediaDetail.as_view()),
|
path('media/<int:pk>/', views.ContentMediaDetail.as_view()),
|
||||||
|
|||||||
@ -95,4 +95,24 @@ class ContentMediaDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
serializer_class = serializers.ContentMediaSerializer
|
serializer_class = serializers.ContentMediaSerializer
|
||||||
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
|
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
|
||||||
search_fields = ['name']
|
search_fields = ['name']
|
||||||
ordering_fields = '__all__'
|
ordering_fields = '__all__'
|
||||||
|
|
||||||
|
class ContentTypeChoices(views.APIView):
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
return Response({
|
||||||
|
"count": len(models.Content.CONTENT_TYPE_CHOICES),
|
||||||
|
"results": [
|
||||||
|
{"value": choice[0], "label": choice[1]}
|
||||||
|
for choice in models.Content.CONTENT_TYPE_CHOICES
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
class ContentStatusChoices(views.APIView):
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
return Response({
|
||||||
|
"count": len(models.Content.CONTENT_STATUS_CHOICES),
|
||||||
|
"results": [
|
||||||
|
{"value": choice[0], "label": choice[1]}
|
||||||
|
for choice in models.Content.CONTENT_STATUS_CHOICES
|
||||||
|
]
|
||||||
|
})
|
||||||
Loading…
Reference in New Issue
Block a user