From 6186a3717b0e3e5f73fb598282c463d0ac567065 Mon Sep 17 00:00:00 2001 From: Irwan Cahyono Date: Thu, 26 Jun 2025 14:39:20 +0700 Subject: [PATCH] character --- freekake_api/character/__init__.py | 0 freekake_api/character/admin.py | 3 ++ freekake_api/character/apps.py | 6 +++ freekake_api/character/models.py | 53 +++++++++++++++++++++++++++ freekake_api/character/serializers.py | 31 ++++++++++++++++ freekake_api/character/tests.py | 3 ++ freekake_api/character/urls.py | 13 +++++++ freekake_api/character/views.py | 41 +++++++++++++++++++++ 8 files changed, 150 insertions(+) create mode 100644 freekake_api/character/__init__.py create mode 100644 freekake_api/character/admin.py create mode 100644 freekake_api/character/apps.py create mode 100644 freekake_api/character/models.py create mode 100644 freekake_api/character/serializers.py create mode 100644 freekake_api/character/tests.py create mode 100644 freekake_api/character/urls.py create mode 100644 freekake_api/character/views.py diff --git a/freekake_api/character/__init__.py b/freekake_api/character/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/freekake_api/character/admin.py b/freekake_api/character/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/freekake_api/character/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/freekake_api/character/apps.py b/freekake_api/character/apps.py new file mode 100644 index 0000000..121ff60 --- /dev/null +++ b/freekake_api/character/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CharacterConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'character' diff --git a/freekake_api/character/models.py b/freekake_api/character/models.py new file mode 100644 index 0000000..5948080 --- /dev/null +++ b/freekake_api/character/models.py @@ -0,0 +1,53 @@ +from django.db import models +from django_softdelete.models import SoftDeleteModel + +class Character(SoftDeleteModel): + + class CharacterType(models.TextChoices): + HUMAN = 'HUMAN', 'Manusia' + ANIMAL = 'ANIMAL', 'Hewan' + + name = models.CharField(max_length=100) + description = models.TextField(blank=True, null=True) + sex = models.BooleanField(blank=False, null=False) + type = models.CharField(max_length=25, choices=CharacterType.choices, default=CharacterType.HUMAN) + + featured_image = models.CharField(max_length=1000) + featured_icon = models.CharField(max_length=1000) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.name + +class CharacterSkin(models.Model): + character = models.ForeignKey(Character, on_delete=models.CASCADE, related_name='skins') + + name = models.CharField(max_length=100) + description = models.TextField(blank=True, null=True) + + featured_image = models.CharField(max_length=1000) + featured_icon = models.CharField(max_length=1000) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.name + +class CharacterFragment(models.Model): + skin = models.ForeignKey(CharacterSkin, on_delete=models.CASCADE) + + name = models.CharField(max_length=100) + description = models.TextField(blank=True, null=True) + + fragment_number = models.PositiveSmallIntegerField() + + featured_icon = models.CharField(max_length=1000) + + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.name diff --git a/freekake_api/character/serializers.py b/freekake_api/character/serializers.py new file mode 100644 index 0000000..b95761c --- /dev/null +++ b/freekake_api/character/serializers.py @@ -0,0 +1,31 @@ +from rest_framework import serializers +from character import models + +class CharacterSerializer(serializers.ModelSerializer): + class Meta: + model = models.Character + fields = ['id', 'name', 'description', 'sex', 'type', 'featured_image', 'featured_icon'] + +class CharacterSkinSerializer(serializers.ModelSerializer): + class Meta: + model = models.CharacterSkin + fields = ['id', 'name', 'description', 'featured_image', 'featured_icon', 'character'] + +class CharacterSkinDetailSerializer(serializers.ModelSerializer): + character = CharacterSerializer(read_only=True) + + class Meta: + model = models.CharacterSkin + fields = ['id', 'name', 'description', 'featured_image', 'featured_icon', 'character'] + +class CharacterFragmentSerializer(serializers.ModelSerializer): + class Meta: + model = models.CharacterFragment + fields = ['id', 'name', 'description', 'fragment_number', 'featured_icon', 'skin'] + +class CharacterFragmentDetailSerializer(serializers.ModelSerializer): + skin = CharacterSkinSerializer(read_only=True) + + class Meta: + model = models.CharacterFragment + fields = ['id', 'name', 'description', 'fragment_number', 'featured_icon', 'skin'] \ No newline at end of file diff --git a/freekake_api/character/tests.py b/freekake_api/character/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/freekake_api/character/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/freekake_api/character/urls.py b/freekake_api/character/urls.py new file mode 100644 index 0000000..d581669 --- /dev/null +++ b/freekake_api/character/urls.py @@ -0,0 +1,13 @@ +from django.urls import path +from character import views + +urlpatterns = [ + path('characters/', views.CharacterList.as_view()), + path('characters//', views.CharacterDetail.as_view()), + + path('character-fragments/', views.CharacterFragmentList.as_view()), + path('character-fragments//', views.CharacterFragmentDetail.as_view()), + + path('character-skins/', views.CharacterSkinList.as_view()), + path('character-skins//', views.CharacterSkinDetail.as_view()), +] diff --git a/freekake_api/character/views.py b/freekake_api/character/views.py new file mode 100644 index 0000000..4631b91 --- /dev/null +++ b/freekake_api/character/views.py @@ -0,0 +1,41 @@ +from rest_framework import generics, filters +from django_filters.rest_framework import DjangoFilterBackend + +from character import models, serializers + +class CharacterList(generics.ListCreateAPIView): + queryset = models.Character.objects.all() + serializer_class = serializers.CharacterSerializer + filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend] + search_fields = ['name'] + filterset_fields = ['type'] + ordering_fields = '__all__' + +class CharacterDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = models.Character.objects.all() + serializer_class = serializers.CharacterSerializer + +class CharacterSkinList(generics.ListCreateAPIView): + queryset = models.CharacterSkin.objects.all() + serializer_class = serializers.CharacterSkinSerializer + filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend] + search_fields = ['name'] + filterset_fields = ['character'] + ordering_fields = '__all__' + + +class CharacterSkinDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = models.CharacterSkin.objects.all() + serializer_class = serializers.CharacterSkinSerializer + +class CharacterFragmentList(generics.ListCreateAPIView): + queryset = models.CharacterFragment.objects.all() + serializer_class = serializers.CharacterFragmentSerializer + filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend] + search_fields = ['name'] + filterset_fields = ['skin'] + ordering_fields = '__all__' + +class CharacterFragmentDetail(generics.RetrieveUpdateDestroyAPIView): + queryset = models.CharacterFragment.objects.all() + serializer_class = serializers.CharacterFragmentSerializer