我正在尝试创建一个没有预定义模型的 REST-ModelViewSet,但在向路由器注册时会采用一个模型。我需要它来动态地将模型添加到我的 REST-API,而不需要配置任何新的 View 集或序列化器。
我的想法是通过 kwargs
中的模型的__init__
,但我不知道如何正确地做到这一点。这是我尝试过的:
//Viewset
class ThemeViewSet(viewsets.ModelViewSet):
def __init__(self, **kwargs):
self.model = kwargs['model']
self.serializer_class = None
super(ThemeViewSet, self).__init__(**kwargs)
def get_serializer_class(self):
if self.serializer_class is not None:
return self.serializer_class
class ThemeSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = self.model
self.serializer_class = ThemeSerializer
return self.serializer_class
//Router:
router = routers.DefaultRouter()
router.register(r'mytheme', ThemeViewSet(model=mytheme), base_name='mytheme')
现在,如果我尝试 print self.model
在__init__
,它正确显示 <class 'myapp.models.mytheme'>
在控制台中,但 Django 仍然返回错误:
AttributeError at /api/mytheme/
This method is available only on the view class.
此错误是由 classonlymethod
引发的-装饰器。我真的不知道该怎么做,有什么方法可以将模型传递给 __init__
,或者我可以尝试其他方法吗?
(我知道 wq.db.rest 有一个路由器可以实现我想要的功能,但我不想使用 wq。我还没有尝试过 tastypie,这会让它变得更容易/可能吗?)
提前致谢!
最佳答案
Django REST Framework 期望 a ViewSet
class被传递到路由器,而不是 View 实例。这是因为必须为每个请求创建实例,这可以防止共享状态带来的许多丑陋问题,并且还遵循标准的 Django 基于类的 View 。
如果您有一种方法可以根据传入的模型创建自定义的 ViewSet
类,那么您可能会运气更好:
class ThemeViewSet(viewsets.ModelViewSet):
@classmethod
def create_custom(cls, **kwargs):
class CustomViewSet(cls):
model = kwargs["model"]
queryset = kwargs["model"].objects.all()
return CustomViewSet
请注意,我还为 View 设置了queryset
,并且自 2.4 发布以来,DRF 不再只接受model
。
这将在每次调用时创建一个新类,并且模型将自动设置为传递给它的模型。当向路由器注册它时,您将执行以下操作:
router.register(r'mytheme', ThemeViewSet.create_custom(model=mytheme), base_name='mytheme')
这样,您仍然会将 ViewSet
类传递给路由器,但它将针对传入的模型进行自定义。您必须确保设置 base_name
,否则路由器将无法生成 View 名称,您最终会遇到错误。
关于python - Django REST Framework - 通过路由器将模型传递给 ViewSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26914459/