Home > Net >  Recursive and nested serializer for CreateAPIView
Recursive and nested serializer for CreateAPIView

Time:10-20

I know there are a few other threads about this topic but none of the solutions seem to work for me.

I have a simple django-treebeard model that allows me to bulk add nested children to a parent via a load_bulk model method.

The POST payload is essentially:

items = [
    {"data": {"title": "1"}, children: []},
    {"data": {"title": "2"}, children: [
        {"data": {"title": "2_1"}, children: []},
        {"data": {"title": "2_2"}, children: [
            {"data": {"title": "2_2_1"}, children: []},
        ]},
    ]},

]

payload = {
    "parent_id": parent_id,
    "items": items
}

I have a view that takes the parent_id and the items list of objects from the payload and passes it to load_bulk to create all the nested objects:

Model.load_bulk(items, parent=Model.objects.get(id=parent_id))

It works fine for the top-level of items but seems to ignore the nested children. In fact, I can't even get the get_children method in my serializer (commented below) to run.

# models.py
class Item(MP_node):
    id = UUIDField()
    title = CharField()

# views.py
class BulkCreateView(generics.CreateAPIView):
    queryset = Item.objects.all()
    serializer_class = BulkCreateSerializer

# serializers.py
class BulkCreateSerializer__item(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ["title"]

class BulkCreateSerializer__wrapper(serializers.ModelSerializer):
    data = TextBulkCreateSerializer__chapter()
    children = serializers.SerializerMethodField()

    class Meta:
        model = Item
        fields = ["data", "children"]

    def get_children(self, obj):
        # Something wrong here? Print statement doesn't even run
        print("get_children")
        return BulkCreateSerializer__chapterWrapper(obj).data

class BulkCreateSerializer(serializers.ModelSerializer):
    parent_id = serializers.UUIDField(required=True)
    chapters = serializers.ListField(
        child=BulkCreateSerializer__wrapper(), write_only=True
    )

    class Meta:
        model = Item
        fields = ["parent_id", "items"]

    def create(self, validated_data):
        # validated_data only contains top-level items
        print("validated_data", validated_data)
        parent_id = validated_data["parent_id"]
        parent = Item.objects.get(id=parent_id)
        chapters = validated_data["chapters"]
        create = Text.load_bulk(chapters, parent=parent)
        return {"parent_id": parent_id}

Edit: So SerializerMethodField is read-only..?

CodePudding user response:

I had the same problem before what I used was a package from drf-writable-nested.

What you can do is simply inherit the WritableNestedModelSerializer into your ModelSerializer.

ex:

class MyModelSerializer(WritableNestedModelSerializer):

    ...

This mixin allows nested relationship for:

  1. OneToOneField()
  2. ForeingKey()
  3. ManyToManyField()
  4. GenericRelation()

CodePudding user response:

djangorestframework-recursive solved it for me simple:

children = serializers.ListField(child=RecursiveField())
  • Related