在我们的项目中,我们有大量的模型,其中一些仍在开发中。我想使用Django Rest Framework创建REST API,但不想为我们拥有的每个模型创建单独的序列化器类和ModelViewSet(因为它们中的大多数应该可以通过API访问)。
当前我们的每个模型都有一个类似的序列化器:
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = '__all__'
此外,在views.py中还有ModelViewSet:
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
是否可以以某种方式减少代码量并使此方法更加灵活?我在想这样的事情:
for model in models:
ser = createSerializer()
createViewSet(ser)
在每次调用的地方都会创建一个单独的类。还是甚至有一个使这成为可能的课程?
答案 0 :(得分:0)
您可以为视图创建一个通用类,然后通过extra url paramaters传递模型和任何其他信息。
例如:
class URLModelAPIView(generics.ListAPIView):
def dispatch(self, request, *args, **kwargs):
self.model = kwargs.pop('model')
self.queryset = self.model.objects.all()
self.serializer = kwargs.pop('serializer')
return super().dispatch(request, *args, **kwargs)
然后在您的urls.py
from django.urls import path
from . import models, serializers, views
urlpatterns = [
path(
'customer/',
views.URLModelAPIView.as_view(),
{
'model': models.Customer,
'serializer': serializers.CustomerSerializer,
}
),
path(
'customer_contact/',
views.URLModelAPIView.as_view(),
{
'model': models.CustomerContact,
'serializer': serializers.CustomerContactSerializer,
}
),
]
使用路由器时,相同的逻辑适用于视图集。
答案 1 :(得分:0)
在@bdoubleus答案的基础上,我们可以使用上述视图集进行少量修改:
class GenericAPIView(generics.ListAPIView):
def dispatch(self, request, *args, **kwargs):
self.model = kwargs.pop('model')
self.queryset = self.model.objects.all()
serializer = GeneralSerializer # Constructor here would throw "'GeneralSerializer' object is not callable"
serializer.Meta.model = self.model
self.serializer_class = serializer
return super().dispatch(request, *args, **kwargs)
第二,我们需要创建一个简单的模板类以在serializers.py
中进行序列化:
from rest_framework import serializers
# Template class for serializing
class GeneralSerializer(serializers.ModelSerializer):
class Meta:
fields = '__all__'
要结束此生成器,我们需要为urls.py
中的每个模型创建一个URL路由:
app = apps.get_app_config('testapp') # Add own app name
for model_name, model in app.models.items():
urlpatterns.append(path(model_name, views.GenericAPIView.as_view(), {'model': model}))