Rob*_*wen 13 python django python-3.x django-rest-framework
当我在django-rest0-framework中创建一个基于ModelSerializer的Serializer时,我将不得不在Meta类中传递模型:
class ClientSerializer(ModelSerializer):
class Meta:
model = Client
Run Code Online (Sandbox Code Playgroud)
我想创建一个通用的序列化程序,它基于URL动态地包含模型.
我的设置因此包括urls.py和viewset:
urls.py:
url(r'^api/v1/general/(?P<model>\w+)', kernel_api_views.GeneralViewSet.as_view({'get':'list'}))
Run Code Online (Sandbox Code Playgroud)
和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')
Run Code Online (Sandbox Code Playgroud)
其中有:http://127.0.0.1:8000 /api/v1/general/Client将Client.objects.all()作为queryset,将ClientSerializer类作为序列化程序
问题:如何制作它以便我可以调用'GeneralSerializer'并动态分配模型?
Rah*_*pta 17
您可以通过以下方式实现:
serializers.py
class GeneralSerializer(serializers.ModelSerializer):
class Meta:
model = None
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
在serializers.py,我们定义GeneralSerializer其model在Meta作为None.我们将model在调用时覆盖该值get_serializer_class().
然后在我们的views.py文件中,我们定义一个GeneralViewSetwith get_queryset()和 get_serializer_class()overridden.
在get_queryset(),我们获取modelfrom 的值kwargs并返回该查询集.
在 get_serializer_class(),我们将modelfor GeneralSerializer的值设置为从中获得的值kwargs然后返回GeneralSerializer.
到目前为止,我知道如果使用模型序列化器,则无法创建通用序列化器,但是可以使用基类并从该基类派生所有模型来获得相同的解决方案。实现一种方法以返回序列化器,然后使用该方法生成动态序列化器。在过去的两年中,我一直在使用这项技术,并且对我来说还算不错-
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
Run Code Online (Sandbox Code Playgroud)
现在从中导出模型-
class Derived1(BaseModel):
pass
class Derived2(BaseModel):
pass
Run Code Online (Sandbox Code Playgroud)
如果要覆盖串行器,则只需在所需的序列器中进行即可。例如 -
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
Run Code Online (Sandbox Code Playgroud)
就是这样,现在每个类都有自己的动态序列化器,但我们只是在一个地方定义了它。
现在在视图集中使用序列化器-
class Derive1ViewSet(ModelViewSet):
serializer_class = Derived1.get_serializer()
class Derive2ViewSet(ModelViewSet):
serializer_class = Derived2.get_serializer()
Run Code Online (Sandbox Code Playgroud)
然后从那里继续。
| 归档时间: |
|
| 查看次数: |
5942 次 |
| 最近记录: |