几乎丢失了:self.parent.parent .__ class__

时间:2016-09-29 11:09:20

标签: python django django-rest-framework

我需要序列化自引用层次结构

class Systm(models.Model):
    ...
    parent = models.ForeignKey('self', on_delete=models.CASCADE, blank = True, null = True, related_name="children")

我能够通过以下代码实现这一目标:

class RecursiveField(serializers.Serializer):
    def to_representation(self, value):
        serializer = self.parent.parent.__class__(value, context=self.context)
        return serializer.data

class SystmSerializer(serializers.ModelSerializer):
    children = RecursiveField(many = True, read_only = True)

    class Meta:
        model = models.Systm
        fields = ('id', 'name', 'type', 'children')

它的工作原理和一切都很明亮,除了我所做的只是复制和粘贴代码,但不知道它是如何工作的以及它的工作原理。这很烦人,我想了解它 我把' print'命令进入' to_representation(...)'但仍不清楚。我了解到,当self.parent.parent.__class__(value, context=self.context)' if (image != nil) { .... } else{ ... } '已执行但不确定原因。 如果有人能向我解释,我真的很感激。

谢谢,

1 个答案:

答案 0 :(得分:0)

这基本上可以通过获取顶级序列化程序类并实例化它来返回子项的序列化值。序列化程序(或字段)的parent属性是将其声明为字段的序列化程序实例。

self.parent是在声明many=True时隐式创建的List Serializer(请参阅ListSerializer)。 self.parent.parentSystmSerializer个实例。

我的猜测是这个代码只有用,因为递归字段已用many=True声明。如果您有child = RecursiveField(read_only = True),则代码为:

class RecursiveField(serializers.Serializer):
    def to_representation(self, value):
        serializer = self.parent.__class__(value, context=self.context)
        return serializer.data

为简单起见,当您(或DRF)调用serialializer_instance.data时,它会调用to_representation来序列化对象实例。

递归在SystmSerializer.to_representation

执行时发挥作用
  1. 调用to_representation(instance)时,会在每个字段上调用to_representation(field_instance)
  2. 其中一个字段是recursiveField,更确切地说是与recursiveField相关联的ListSerializer
  3. ListSerializer上拨打to_representation会为{1}}的所有孩子(如果有)致电。{/ li>
  4. 这是递归开始时:recursiveField.to_representation(child)的实现会在子recursiveField.to_representation对象上实例化一个新SystmSerializer实例,然后调用Systm,它本身会触发{{1}调用...然后您回到第1步,在SystmSerializer.data个子对象上添加了一个新的to_representation实例。
  5. 当没有孩子时,递归结束。当然,如果孩子引用了祖先,你可能会遇到无休止的递归。