有办法动态生成Django rest框架序列化器吗?
考虑到这一点:
class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = models.Blog
fields = get_all_model_fields(models.Blog)
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = models.Post
fields = get_all_model_fields(models.Post)
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = get_all_model_fields(models.User)
我想知道是否可以像下面这样的例子:
from django.apps import apps
models = [model for model in apps.get_models()]
for model in models:
type(model.__name__+'Serializer',(serializers.ModelSerializer,),{
type("Meta",(),{
"model":model,
"fields": get_all_model_fields(model)
})
})
或者有没有其他方法来生成DRF串行化器?
发布于 2021-04-25 06:11:13
下面是为给定的ModelSerializer
构建Model
的函数(用Django 3.2、DRF 3.12.4和Python3.8进行测试):
from functools import lru_cache
from typing import Type
from django.db import models
from rest_framework import serializers
@lru_cache(maxsize=0)
def model_serializer(model: Type[models.Model]) -> Type[serializers.ModelSerializer]:
meta_class = types.new_class("Meta")
setattr(meta_class, "model", model)
setattr(meta_class, "fields", "__all__")
result = types.new_class(
model.__name__ + "Serializer", (serializers.ModelSerializer,), {}
)
setattr(result, "Meta", meta_class)
return result
如果您确信只对每个序列化程序调用该函数一次,则可以省略缓存以保留一些内存。
示例用法:
class MyModel(models.Model):
some = models.CharField(max_length=123)
other = models.IntegerField()
MyModelSerializer = model_serializer(MyModel)
my_serializer = MyModelSerializer({"some": "abc", "other": 1234})
my_serializer.is_valid(True)
若要将所有模型的序列化器添加到当前模块的命名空间,请执行以下操作:
from django.apps import apps
for model in apps.get_models():
serializer_type = model_serializer(model)
globals()[serializer_type.__name__] = serializer_type
发布于 2020-11-12 21:05:22
您的方法是可行的,但是Django要想找到这些序列化器,就必须将它们分配给模块命名空间。
在您的代码中,只需调用type
--将立即创建序列化程序类并“丢弃”。即使基本Django类serializers.ModelSerializer
在注册表中保留了对它的引用,您也无法导入序列化程序并使用它们。
您所要做的就是将它们添加到globals()
返回的字典中。类似地,您为该类创建的命名空间还必须是一个字典( -since ),您正在调用" type“,但实际上没有将它的名称指定为"Meta",而是创建了一个集合,而不是一个字典,您对类型的调用将失败,因为它期待一个字典。
因此,我没有检查代码是否实际工作,但基于您的想法是:
from django.apps import apps
models = [model for model in apps.get_models()]
for model in models:
name = f"{model.__name__}Serializer"
globals()[name] = type(name,(serializers.ModelSerializer,),{
"Meta": type("Meta",(),{
"model":model,
"fields": get_all_model_fields(model)
})
})
del models, model, name
https://stackoverflow.com/questions/64810287
复制相似问题