Django rest框架从Serializer继承一个类并将其抽象

时间:2018-08-14 10:44:28

标签: python django oop django-rest-framework

我正在将Python 3.6与Django 1.11.9和rest_framework 3.6.2结合使用。

我想从serializers.Serializer继承,以创建一个我想抽象的SharingSerializer类,因为我想从后者继承以实现一些ArticleSharingSerializer,ImageSharingSerializer等。

到目前为止,我已经尝试过:

from abc import ABCMeta, abstractmethod
from rest_framework import serializers
...

class SharingSerializer(serializers.Serializer, metaclass=ABCMeta):
    course = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all())
    students = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), many=True)

    @abstractmethod
    def validate(self, data):
        # Doing validation stuff with "course" and "students" fields
        ...
        return data


class ArticleSharingSerializer(SharingSerializer):
    articles = serializers.PrimaryKeyRelatedField(queryset=Article.objects.all(), many=True)

    def validate(self, data):
        data = super().validate(data)
        # Doing validation stuff with "articles" and self.context["request"].user
        ...
        return data

但是当尝试“运行服务器”时,出现以下错误:

File ".../school/serializers.py", line 11, in <module>
class SharingSerializer(serializers.Serializer, metaclass=ABCMeta):
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

您知道我如何成功实现自己想要达到的目标吗?

更新:我想在ABC提供的实例化中利用@abstractmethod“ enforcement”。

更新2:TLDR:艾哈迈德·霍斯尼(Ahmed Hosny,见下文)给出的最佳答案是this link

1 个答案:

答案 0 :(得分:0)

简短回答

要继续使用ABCMeta,您也可以这样做,

class SharingSerializer(serializers.Serializer):
    __metaclass__ = ABCMeta

    course = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all())
    students = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), many=True)

    @abstractmethod
    def validate(self, data):
        # Doing validation stuff with "course" and "students" fields
        ...
        return data

或进行中级学习,请检查此OP

详细答案:

当您尝试让一个类继承自具有不同meta_class的两个不同类时,就会出现问题。然后发生冲突!

因此,在您的情况下,您从具有元类的serializers.Serializer继承(选中this),并且还通过meta_class继承了不同的metaclass=ABCMeta。这就是发生冲突的原因。

还要检查此reference和此one

[更新]

让我们明确几点:

  • 正在做

    class Meta: abstract = True 不会使您的类抽象化您对Java和其他编译语言的了解。

实际上,它只是使用一些额外的属性标记了该类(无需进一步说明)。

所以这不是特定于Django的,abstract = True本身没有任何内容也不会做任何额外的事情。