✏️ Fix: [#99] 노코드툴 모델 대규모 수정
This commit is contained in:
@@ -1,30 +1,67 @@
|
||||
from rest_framework import serializers
|
||||
from .models import Code, Page, Element
|
||||
|
||||
# from datetime import datetime, timezone
|
||||
|
||||
from django.utils import timezone
|
||||
# from zoneinfo import ZoneInfo
|
||||
|
||||
# KST = ZoneInfo("Asia/Seoul")
|
||||
from .models import Code, Page, CraftNode, NodeType # (네 models.py에 맞춰 import)
|
||||
|
||||
class ElementSerializer(serializers.Serializer):
|
||||
element_id = serializers.CharField(required=False)
|
||||
element_type = serializers.CharField()
|
||||
content = serializers.CharField(allow_blank=True)
|
||||
css = serializers.DictField()
|
||||
|
||||
# -------------------------
|
||||
# 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):
|
||||
cut = serializers.IntegerField()
|
||||
elements = ElementSerializer(many=True)
|
||||
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()
|
||||
pages = PageSerializer(many=True, required=False)
|
||||
keyword = serializers.ListField(child=serializers.CharField(), required=False, allow_empty=True)
|
||||
description = serializers.CharField(allow_blank=True, required=False)
|
||||
created_at = serializers.SerializerMethodField()
|
||||
updated_at = 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")
|
||||
@@ -32,46 +69,77 @@ class CodeSerializer(serializers.Serializer):
|
||||
def get_updated_at(self, obj):
|
||||
return timezone.localtime(obj.updated_at).isoformat(timespec="seconds")
|
||||
|
||||
def get_id(self, obj):
|
||||
return str(obj.id)
|
||||
# -------------------------
|
||||
# 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 = [
|
||||
Page(
|
||||
cut=page['cut'],
|
||||
elements=[Element(**el) for el in page['elements']]
|
||||
) for page in pages_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):
|
||||
update_pages_data = validated_data.get('pages', [])
|
||||
existing = {p.cut: p for p in instance.pages}
|
||||
|
||||
for page in update_pages_data:
|
||||
cut = page.get('cut')
|
||||
if cut and cut in existing:
|
||||
page_obj = existing[cut]
|
||||
page_obj.elements = [Element(**el) for el in page["elements"]]
|
||||
|
||||
else:
|
||||
instance.pages.append(
|
||||
Page(
|
||||
cut=cut,
|
||||
elements=[Element(**el) for el in page["elements"]]
|
||||
)
|
||||
)
|
||||
# pages는 page_id 기준으로 upsert
|
||||
update_pages_data = validated_data.get("pages", [])
|
||||
existing = {p.page_id: p for p in instance.pages}
|
||||
|
||||
if 'keyword' in validated_data:
|
||||
instance.keyword = validated_data['keyword']
|
||||
if 'description' in validated_data:
|
||||
instance.description = validated_data['description']
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user