Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python django rest框架&x2B;django多态模型序列化_Python_Django_Django Rest Framework - Fatal编程技术网

Python django rest框架&x2B;django多态模型序列化

Python django rest框架&x2B;django多态模型序列化,python,django,django-rest-framework,Python,Django,Django Rest Framework,我想知道是否有人有一个结合Django REST框架和Django多态性的Python解决方案 鉴于: class GalleryItem(PolymorphicModel): gallery_item_field = models.CharField() class Photo(GalleryItem): custom_photo_field = models.CharField() class Video(GalleryItem): custom_image_fi

我想知道是否有人有一个结合Django REST框架和Django多态性的Python解决方案

鉴于:

class GalleryItem(PolymorphicModel):
    gallery_item_field = models.CharField()

class Photo(GalleryItem):
    custom_photo_field = models.CharField()

class Video(GalleryItem):
    custom_image_field = models.CharField()

如果我想要django rest框架中所有GalleryItem的列表,它只会给我GalleryItem(父模型)的字段,因此:id、gallery_item_字段和多态性_ctype。那不是我想要的。如果是照片实例,我需要自定义\u photo\u字段;如果是视频,我需要自定义\u image\u字段。

到目前为止,我只针对GET请求测试了此字段,此操作有效:

class PhotoSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Photo


class VideoSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Video


class GalleryItemModuleSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.GalleryItem

    def to_representation(self, obj):
        """
        Because GalleryItem is Polymorphic
        """
        if isinstance(obj, models.Photo):
            return PhotoSerializer(obj, context=self.context).to_representation(obj)
        elif isinstance(obj, models.Video):
           return VideoSerializer(obj, context=self.context).to_representation(obj)
        return super(GalleryItemModuleSerializer, self).to_representation(obj)

对于POST和PUT请求,您可能希望执行类似的操作,如使用to_internal_value def覆盖to_表示定义。

为了完成,我将
添加到\u internal_value()
实现中,因为我在最近的项目中需要它

如何确定类型

它很方便,可以区分不同的“类”;为此,我将type属性添加到基本多态模型中:

class GalleryItem(PolymorphicModel):
    gallery_item_field = models.CharField()

    @property
    def type(self):
        return self.__class__.__name__
这允许将
类型
称为“字段”和“只读字段”

type
将包含python类名

向序列化程序添加类型

您可以将
类型添加到“字段”和“只读字段”中
(如果要在所有子模型中使用序列化器,则需要在所有序列化器中指定类型字段)


这是一个通用的、可重用的解决方案。它适用于通用的
序列化程序
,但修改它以使用
ModelSerializer
并不困难。它也不处理序列化父类(在我的例子中,我更多地将父类用作接口)

使用它:

class ParentClassSerializer(PolymorphicSerializer):
    """
    Serializer for ParentClass objects
    """
    def get_serializer_map(self) -> Dict[str, serializers.Serializer]:
        """
        Return serializer map
        """
        return {
            ChildClass1.__name__: ChildClass1Serializer,
            ChildClass2.__name__: ChildClass2Serializer,
        }

我找不到
to_native
方法的任何文档。什么时候调用?我猜POST和PUT可能会稍微困难一些(尽管仍然可行),因为您需要在验证之前确定用户打算提交什么(如果缺少字段,可能无法确定)。我的意思是,在写请求时使用单独的端点更干净。将
改为\u native
改为
改为\u representation
。很好的解决方案!您是否能够将其与DRF的可浏览文档集成?谢谢,我不熟悉可浏览文档,所以我不熟悉。谢谢您提供此解决方案。快速提示:序列化程序映射的类型应该是
Dict[str,type[serializers.serializer]]
而不是
Dict[str,serializers.serializer]
from typing import Dict, Type

from rest_framework import serializers


class PolymorphicSerializer(serializers.Serializer):
    """
    Serializer to handle multiple subclasses of another class

    - For serialized dict representations, a 'type' key with the class name as
      the value is expected: ex. {'type': 'Decimal', ... }
    - This type information is used in tandem with get_serializer_map(...) to
      manage serializers for multiple subclasses
    """
    def get_serializer_map(self) -> Dict[str, Type[serializers.Serializer]]:
        """
        Return a dict to map class names to their respective serializer classes

        To be implemented by all PolymorphicSerializer subclasses
        """
        raise NotImplementedError

    def to_representation(self, obj):
        """
        Translate object to internal data representation

        Override to allow polymorphism
        """
        type_str = obj.__class__.__name__

        try:
            serializer = self.get_serializer_map()[type_str]
        except KeyError:
            raise ValueError(
                'Serializer for "{}" does not exist'.format(type_str),
            )

        data = serializer(obj, context=self.context).to_representation(obj)
        data['type'] = type_str
        return data

    def to_internal_value(self, data):
        """
        Validate data and initialize primitive types

        Override to allow polymorphism
        """
        try:
            type_str = data['type']
        except KeyError:
            raise serializers.ValidationError({
                'type': 'This field is required',
            })

        try:
            serializer = self.get_serializer_map()[type_str]
        except KeyError:
            raise serializers.ValidationError({
                'type': 'Serializer for "{}" does not exist'.format(type_str),
            })

        validated_data = serializer(context=self.context) \
            .to_internal_value(data)
        validated_data['type'] = type_str
        return validated_data

    def create(self, validated_data):
        """
        Translate validated data representation to object

        Override to allow polymorphism
        """
        serializer = self.get_serializer_map()[validated_data['type']]
        return serializer(context=self.context).create(validated_data)
class ParentClassSerializer(PolymorphicSerializer):
    """
    Serializer for ParentClass objects
    """
    def get_serializer_map(self) -> Dict[str, serializers.Serializer]:
        """
        Return serializer map
        """
        return {
            ChildClass1.__name__: ChildClass1Serializer,
            ChildClass2.__name__: ChildClass2Serializer,
        }