首页 > 解决方案 > Django rest框架从Serializer继承一个类并使其抽象

问题描述

我将 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“强制”。

更新 2:TLDR:Ahmed Hosny 给出的最佳答案(见下文)是这个链接

标签: pythondjangooopdjango-rest-framework

解决方案


简答

要继续使用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一个元类(检查这个),并且你继承了一个不同meta_class的 by metaclass=ABCMeta。这就是发生冲突的原因。

还要检查这个参考这个

[更新]

让我们明确几点:

  • 正在做

    class Meta: abstract = True 不会使您的类抽象为您在 Java 和其他编译语言中所知道的方式。

它实际上所做的只是用一些额外的属性标记这个类(没有更多细节)。

所以它不是 Django 特定的,abstract = True单独没有任何东西也不会做任何额外的事情。


推荐阅读