Files
colio/nocodetools/serializers.py
2025-12-29 17:46:26 +09:00

146 lines
4.7 KiB
Python

from rest_framework import serializers
from django.utils import timezone
from .models import Code, Page, CraftNode, NodeType # (네 models.py에 맞춰 import)
# -------------------------
# Node (CraftJS)
# -------------------------
class NodeTypeSerializer(serializers.Serializer):
resolvedName = serializers.CharField()
class CraftNodeSerializer(serializers.Serializer):
type = NodeTypeSerializer()
isCanvas = serializers.BooleanField(required=False, default=False)
props = serializers.DictField(required=False, default=dict)
displayName = serializers.CharField(required=False, allow_blank=True, allow_null=True)
custom = serializers.DictField(required=False, default=dict)
hidden = serializers.BooleanField(required=False, default=False)
nodes = serializers.ListField(child=serializers.CharField(), required=False, default=list)
linkedNodes = serializers.DictField(required=False, default=dict)
parent = serializers.CharField(required=False, allow_null=True, allow_blank=True)
# -------------------------
# Page
# -------------------------
class PageSerializer(serializers.Serializer):
page_id = serializers.IntegerField()
title = serializers.CharField()
# data: { "ROOT": {...}, "mBIaZ3L5VU": {...}, ... }
# -> key는 문자열(node id), value는 CraftNode
data = serializers.DictField(
child=CraftNodeSerializer(),
required=False,
default=dict,
)
# -------------------------
# Code
# -------------------------
class CodeSerializer(serializers.Serializer):
id = serializers.SerializerMethodField()
keyword = serializers.ListField(
child=serializers.CharField(max_length=50),
required=False,
allow_empty=True,
default=list,
)
description = serializers.CharField(required=False, allow_blank=True, default="")
pages = PageSerializer(many=True, required=False, default=list)
created_at = serializers.SerializerMethodField()
updated_at = serializers.SerializerMethodField()
def get_id(self, obj):
return str(obj.id)
def get_created_at(self, obj):
return timezone.localtime(obj.created_at).isoformat(timespec="seconds")
def get_updated_at(self, obj):
return timezone.localtime(obj.updated_at).isoformat(timespec="seconds")
# -------------------------
# helpers: dict -> EmbeddedDocument
# -------------------------
def _to_node_type(self, data: dict) -> NodeType:
return NodeType(resolvedName=data.get("resolvedName", ""))
def _to_craft_node(self, data: dict) -> CraftNode:
# type 필수
node_type = self._to_node_type(data["type"])
return CraftNode(
type=node_type,
isCanvas=data.get("isCanvas", False),
props=data.get("props", {}) or {},
displayName=data.get("displayName"),
custom=data.get("custom", {}) or {},
hidden=data.get("hidden", False),
nodes=data.get("nodes", []) or [],
linkedNodes=data.get("linkedNodes", {}) or {},
parent=data.get("parent"),
)
def _to_page(self, page: dict) -> Page:
raw_map = page.get("data", {}) or {}
node_map = {node_id: self._to_craft_node(node_dict) for node_id, node_dict in raw_map.items()}
return Page(
page_id=page["page_id"],
title=page["title"],
data=node_map,
)
# -------------------------
# create / update
# -------------------------
def create(self, validated_data):
request = self.context["request"]
validated_data["object_type"] = request.query_params.get("type")
validated_data["object_id"] = request.query_params.get("id")
pages_data = validated_data.pop("pages", [])
pages = [self._to_page(p) for p in pages_data]
code = Code(pages=pages, **validated_data)
code.save()
return code
def update(self, instance, validated_data):
# pages는 page_id 기준으로 upsert
update_pages_data = validated_data.get("pages", [])
existing = {p.page_id: p for p in instance.pages}
for page in update_pages_data:
pid = page.get("page_id")
if pid is None:
continue
new_page_obj = self._to_page(page)
if pid in existing:
page_obj = existing[pid]
page_obj.title = new_page_obj.title
page_obj.data = new_page_obj.data
else:
instance.pages.append(new_page_obj)
if "keyword" in validated_data:
instance.keyword = validated_data["keyword"]
if "description" in validated_data:
instance.description = validated_data["description"]
instance.save()
return instance