首页 文章

在Meta中使用动态模型创建通用序列化程序

提问于
浏览
7

当我在django-rest0-framework中创建一个基于ModelSerializer的Serializer时,我将不得不在Meta类中传递模型:

class ClientSerializer(ModelSerializer):
    class Meta:
        model = Client

我想创建一个通用的序列化程序,它基于URL动态地包含模型 .

我的设置因此包括urls.py和viewset:

urls.py:

url(r'^api/v1/general/(?P<model>\w+)', kernel_api_views.GeneralViewSet.as_view({'get':'list'}))

和views.py:

class GeneralViewSet(viewsets.ModelViewSet):

     def get_queryset(self):
            # Dynamically get the model class from myapp.models
            queryset = getattr(myapp.models, model).objects.all()
            return queryset

     def get_serializer_class(self):
         return getattr(myapp.serializers, self.kwargs['model']+'Serializer')

其中包含:http://127.0.0.1:8000/api/v1/general/Client将Client.objects.all()作为queryset,将ClientSerializer类作为序列化程序

Question: 如何制作它以便我可以调用'GeneralSerializer'并动态分配模型?

4 回答

  • 4

    您可以通过以下方式实现:

    serializers.py

    class GeneralSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = None
    

    views.py

    class GeneralViewSet(viewsets.ModelViewSet):
    
         def get_queryset(self):
             model = self.kwargs.get('model')
             return model.objects.all()           
    
         def get_serializer_class(self):
             GeneralSerializer.Meta.model = self.kwargs.get('model')
             return GeneralSerializer
    

    serializers.py 中,我们将 GeneralSerializer 定义为 MetaMetaNone . 我们将在调用 get_serializer_class() 时覆盖 model 值 .

    然后在我们的 views.py 文件中,我们定义 GeneralViewSet ,其中 get_queryset()get_serializer_class() 被覆盖 .

    get_queryset() 中,我们从 kwargs 获取 model 的值并返回该查询集 .

    get_serializer_class() 中,我们将 GeneralSerializermodel 的值设置为从 kwargs 获得的值,然后返回 GeneralSerializer .

  • 0

    到目前为止,我知道如果使用模型序列化程序,则无法创建通用序列化程序,但您可以使用基类获取相同的解决方案,并从该基类派生所有模型 . 实现返回序列化程序的方法,然后使用该方法生成动态序列化程序 . 我在过去的两年里使用这种技术并且对我来说工作得很好 -

    class BaseModel(models.Model):
        class Meta:
             abstract = True # define abstract so that it does not cause any problem with model hierarchy in database
    
        @classmethod
        def get_serializer(cls):
             class BaseSerializer(serializers.ModelSerializer):
                   class Meta:
                        model = cls # this is the main trick here, this is how I tell the serializer about the model class
    
             return BaseSerializer #return the class object so we can use this serializer
    

    现在从中推导出你的模型 -

    class Derived1(BaseModel):
        pass
    
    class Derived2(BaseModel):
        pass
    

    如果要覆盖序列化程序,那么只需在您需要的那个中执行 . 例如 -

    class DerivedOverride(BaseModel):
        @classmethod
        def get_serializer(cls):
             super_serializer = BaseModel.get_serializer() # this important to not to break the serializing hierarchy
             class BaseSerializer(super_serializer):
                   class Meta:
                        model = cls # this is the main trick here, this is how I tell the serializer about the model class
    
             return BaseSerializer
    

    多数民众赞成,现在每个类都有自己的动态序列化器,但我们只是在一个地方定义它 .

    现在在视图集中使用序列化程序 -

    class Derive1ViewSet(ModelViewSet):
        serializer_class = Derived1.get_serializer()
    
    class Derive2ViewSet(ModelViewSet):
        serializer_class = Derived2.get_serializer()
    

    然后从那里继续

  • 1

    以Rahul的答案为基础,这对我有用:

    urls.py

    url(r'^api/(?P<app_label>\w+)/(?P<model_name>\w+)', GeneralViewSet.as_view({'get': 'list'}))
    

    serializers.py

    from rest_framework import serializers
    class GeneralSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = None
    

    views.py

    from django.apps import apps        
    class GeneralViewSet(viewsets.ModelViewSet):
    
        @property
        def model(self):
            return apps.get_model(app_label=str(self.kwargs['app_label']), model_name=str(self.kwargs['model_name']))
    
        def get_queryset(self):
            model = self.model
            return model.objects.all()           
    
        def get_serializer_class(self):
            GeneralSerializer.Meta.model = self.model
            return GeneralSerializer
    
  • 9

    Meta 中创建不带 model 的通用序列化程序:

    class GeneralModelSerializer(serializers.ModelSerializer):
        ...
    

    在``中将 model 添加到序列化器:

    class GenericViewSet(viewsets.ModelViewSet):
    
        def get_serializer_class(self):
            serializer_class = GeneralModelSerializer
            serializer_class.Meta.model = YourModel
            return serializer_class
    

相关问题