代码之家  ›  专栏  ›  技术社区  ›  Eugene

DRF将数据传递到RelatedField

  •  0
  • Eugene  · 技术社区  · 6 年前

    我有一个序列化程序和一个用于泛型外键关系的相关字段 应该用来序列化 content_object 这是一个 ContentType 实例。我要检查一下 type Notification 对象,我正在相关字段中序列化该对象,以便正确地知道要序列化到 data 参数在里面。实现这一目标的最佳方法是什么?

    class NotificationRelatedField(serializers.RelatedField):
    
        def to_representation(self, value):
            data = {}
            # Need to check notification 'type' here
            return data
    
    
    class NotificationRetrieveSerializer(serializers.ModelSerializer):
        content_object = NotificationRelatedField(read_only=True)
    
        class Meta:
            model = Notification
            fields = [
                'id',
                'created_at',
                'is_read',
                'type',
                'content_object',
            ]
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   JPG    6 年前

    可以使用 SerializerMethodField 作为,

    class Content_Model_1_serializer(serializers.ModelSerializer):
        # you code
    class Content_Model_2_serializer(serializers.ModelSerializer):
        # your code
    
    class NotificationRetrieveSerializer(serializers.ModelSerializer):
        content_object = serializers.SerializerMethodField(read_only=True)
    
        def get_content_object(self, notification):
            if isinstance(notification.content_object, Content_Model_1):
                return Content_Model_1_serializer(notification.content_object).data
            if isinstance(notification.content_object, Content_Model_2):
                return Content_Model_2_serializer(notification.content_object).data
            ## and so on
            return None  # default case
    
        class Meta:
            model = Notification
            fields = [
                'id',
                'created_at',
                'is_read',
                'type',
                'content_object',
            ]

    Content_Model_1 Content_Model_2 是由一般的FK关系和 Content_Model_1_serializer Content_Model_2_serializer 是第三个序列化程序。

        2
  •  1
  •   Sachin    6 年前

    您需要重写序列化程序的 to_representation 方法调用字段的 代表 方法与 Notification 实例,而不是字段的值。

    例子 :

    class NotificationRetrieveSerializer(serializers.ModelSerializer):
        content_object = NotificationRelatedField(read_only=True)
    
        class Meta:
            model = Notification
            fields = [
                'id',
                'created_at',
                'is_read',
                'type',
                'content_object',
            ]
    
        # override to_representation method
        def to_representation(self, instance):
            # python3 for `super` call
            result = super().to_representation(instance)
    
            # python2 for `super` call
            # result = super(
            #     NotificationRetrieveSerializer, self
            # ).to_representatio(instance)
    
            # here you call your field's `to_representation` with current instance
            # as the argument rather than as the `value` of the field.
            result['content_object'] = content_object_field.to_representation(instance)
    
            return result
    
    class NotificationRelatedField(serializers.RelatedField):
    
        # here `value` is now the `Notification` instance
        def to_representation(self, value):
            data = {}
    
            # get the type and this field's value
            type = value.type
            content_object = value.content_object
    
            return data