我有以下django / python片段:
from rest_framework import serializers
from .models import Profile, Task
class Serializable():
types = {}
def __init__(self, objectid):
self.object = self.types[objectid][0]
self.serializer = self.types[objectid][1]
def serialized(self):
instances = self.object.objects.all()
serialized = self.serializer(instances, many=True)
return serialized
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
oid = 'profile'
model = Profile
fields = ['login', 'status']
Serializable.types[oid] = [model, <class-reference>]
class TaskSerializer(serializers.ModelSerializer):
class Meta:
oid = 'task'
model = Task
fields = ['description', 'date', 'owner']
Serializable.types[oid] = [model, <class-reference>]
我正在使用安装了rest_framework
库的Django。我使用的一个有趣的功能是ModelSerializers
(ModelSerializers Documentation),它可以节省大量代码重复。我希望在运行时填充Serializable.types
变量(当声明所有序列化程序类时)。这一点的重点在于,当包含新型号时,我不必更新我的观点。例如,我将打印模型实例的json表示,如下所示:
class QueryObject(APIView):
permission_classes = (AllowAny,)
def get(self, request, *args, **kwargs):
oid = request.GET['oid']
serializable= Serializable(oid)
json = serializable.serialized
return JsonResponse(json)
主要问题在于每个Serializer
类的最后一行。
Serializable.types[oid] = [model, <class-reference>]
我试过把类的名称ProfileSerializer
作为例子,但无济于事。我尝试在Meta
类之外做同样的事情,例如:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
oid = 'profile'
model = Profile
fields = ['login', 'status']
Serializable.types[Meta.oid] = [Meta.model, ProfileSerializer]
也没有成功。不知道还能做什么,这就是为什么我希望社区能帮助我解决这个问题。
答案 0 :(得分:2)
实际上这是定义元类的一种情况。
我从来没有真正找到一个信息来源,它提供了关于什么是元类或它们如何工作的完整,清晰和令人满意的解释。如果需要,我会尝试使用这些信息来增强这个答案,但目前我将坚持为您目前的问题找到解决方案。我假设是python 3。
定义一个额外的类,因此:
class ModelSerializerMeta(serializers.SerializerMetaclass):
def __init__(cls, class_name, base_classes, attributes):
super(ModelSerialiserMeta, cls).__init__(class_name, base_classes, attributes)
Serializer.types[cls.Meta.oid] = [cls.Meta.model, cls]
然后将其用作序列化程序的元类,例如
class ProfileSerializer(serializers.ModelSerializer, metaclass=ModelSerializerMeta):
class Meta:
oid = 'profile'
model = Profile
fields = ['login', 'status']
更好的是,为所有模型序列化器创建一些超类,在那里分配元类,使所有序列化程序继承自该超类,然后在整个类中使用元类。
答案 1 :(得分:1)
除非您的代码需要python&gt; = 3.6,否则元类绝对是正确的答案。从3.6开始,有一个名为__init_subclass__
hook的新功能。
所以你可以做点什么
class foo:
@classmethod
def __init_subclass__(cls, *args, **kwargs):
Serializers.register_class(cls)
每当定义Foo
的孩子时,都会调用__init_subclass__
上的Foo
方法,并将子类引用传递为cls
。