如何在 Django Rest Framework 3 中覆盖 ModelViewSet 的 get_queryset?

How do you override a ModelViewSet's get_queryset in Django Rest Framework 3?

我曾经在 Django Rest Framework (DRF) 2 中遵循这种模式:

class Foo(models.Model):
    user = models.ForeignKey(User)

class FooSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Foo
        fields = ('url')

class FooViewset(viewsets.ModelViewSet):
    def get_queryset(self):
        return Foo.objects.filter(user=self.request.user)
    serializer = FooSerializer
    model = Foo # <-- the way a ModelViewSet is told what the object is in DRF 2

[ in urls.py]
from rest_framework import routers
router = routers.DefaultRouter()
router.register('Foo', views.FooViewSet)

在 DRF 3 中,我现在得到:

AssertionError at /
`base_name` argument not specified, and could not automatically  
 determine the name from the viewset, as it does not have a   
`.queryset` attribute.

如何为 rest_framework.viewsets.ModelViewSet 的实例覆盖 get_queryset

想通了这一点。 rest_framework.viewsets.ModelViewSetmodel 字段似乎在 DRF3 中擅离职守。现在,如果您覆盖 get_queryset,则需要为 routers.DefaultRouter().register 指定第三个参数,即 basename 参数。然后,该函数不会关闭并尝试在 ModelViewSet.

的不存在的 queryset 字段中找到它

例如

router = routers.DefaultRouter()
[...]
router.register('/rest/FooBar'/, views.FooBarViewSet, 'foobar-detail')
                                                     #^^^^^^^^^^^^^^^

要覆盖 DRF 3 中的默认查询集,只需在 FooViewSet class.

中定义 queryset 属性
class FooViewset(viewsets.ModelViewSet):
     queryset = Foo.objects.all()

除了 Ross Rogers 的回答之外,在当前版本 (3.8.2) 上,您只能指定模型的名称而不是处理程序。所以,而不是:

router.register('/rest/FooBar', views.FooBarViewSet, base_name='foobar-list')
router.register('/rest/FooBar/{pk}', views.FooBarViewSet, base_name='foobar-detail')

你可以这样做:

router.register('/rest/FooBar', views.FooBarViewSet, base_name='foobar')