在Django中,如何序列化mptt树?
作者:互联网
以下是我的代码:
class File(MPTTModel):
name=models.CharField(max_length=36, primary_key=True)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
num=models.IntegerField(null=True)
class MPTTMeta:
order_insertion_by = ['name']
我尝试使用以下代码序列化此类:
class RecursiveField(serializers.Serializer):
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
class FileSerializer(serializers.ModelSerializer):
parent=RecursiveField(many=True)
class Meta:
model = File
fields=('name','num','parent')
但是我失败了,因为我只能输出该树的根节点的内容,似乎序列化程序无法访问根的子节点,进而无法访问子节点的子节点…
特定的问题是,在输出中,“父母”被显示为“空”,但实际上它有4个孩子,每个孩子都包含几个后代.
我的代码有什么问题?
谢谢大家的帮助!
解决方法:
MPTT或REST框架都没有魔力.
MPTT将新字段添加到模块中,以实现a nested set model.它还会跟踪从子级到其父级的向上链接,该链接用于某些优化,并在嵌套集树损坏时重建嵌套集树.
因此,基本上,您的模型具有以下字段(您手动添加的名称/数字),为触发MPTT添加的父字段和以下自动字段:
> tree_id:树标识符.附加到相同根的所有节点共享相同的tree_id.
>层:节点在树中的深度.
> lft / rght:嵌套的集合索引.请参阅上面的链接,但是基本思想是,如果一个节点的lft大或等于其rght小于或等于另一个节点的rft,则该节点是另一个节点的后代.
REST框架不支持mptt,并且不需要.它只会看到一个具有7个字段的常规模型,并会很高兴地对其进行序列化.
虽然您可以实现递归序列化器以在…的对象的对象的嵌套对象中对序列化的表示形式进行整形,但在这一点上通常不是一个好主意.
现在,如果您确实想这样做,则需要以其他方式进行.您必须序列化根节点,并确保其序列化表示形式以递归方式包括其所有子节点.就像您在这里尝试的那样,并非相反.
这个想法是构造这样的东西:
class FileSerializer(serializers.ModelSerializer):
children = FileSerializer(many=True)
class Meta:
model = File
fields=('name','num')
但是您不能以这种方式进行操作,因为FileSerializer尚未在您需要的位置定义.您可以尝试覆盖构造函数,并在其中插入其他序列化器,如下所示:
class FileSerializer(serializers.ModelSerializer):
class Meta:
model = File
fields=('name','num')
def get_fields(self):
fields = super(FileSerializer, self).get_fields()
fields['children'] = FileSerializer(many=True)
return fields
未经测试,但您明白了.
然而:
>以这种幼稚的方式执行此操作确实不是一个好主意,因为树中的每个非叶节点都将触发对数据库的附加查询以获取其子级.
>这不适用于反序列化.
只是序列化平面节点,如果确实需要,可以在客户端重建对象树呢?
[{'id': 1, 'name': 'foo', 'parent': null}, // /foo
{'id': 2, 'name': 'bar1', 'parent': 1}, // /foo/bar1
{'id': 3, 'name': 'bar2', 'parent': 1}, // /foo/bar2
{'id': 4, 'name': 'foo2', 'parent': null}, // /foo2
{'id': 5, 'name': 'baz1', 'parent': 4}, // /foo2/baz1
{'id': 6, 'name': 'baz2', 'parent': 4}] // /foo2/baz2
标签:django-mptt,python,django 来源: https://codeday.me/bug/20191028/1950692.html