我有2个模型,它们连接成ManyToMany,如下所示。 我要达到的目标是;仅当用户在该人所属的列表上至少具有查看权限时,才向用户提供服务。
这是我的简化模型;
class List(TimeStampedModel, UserAwareModel):
"""Model definition for List."""
name = models.CharField(_('list name'), max_length=50)
...
class Person(TimeStampedModel, UserAwareModel):
"""Model definition for Person."""
member = models.ManyToManyField(List, blank=True)
...
这是我的观点;
class ListViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows Lists to be viewed or edited.
"""
queryset = List.objects.all()
serializer_class = ListSerializer
permission_classes = (CustomObjectPermissions, DjangoModelPermissions)
filter_backends = (filters.DjangoObjectPermissionsFilter,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class PersonViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows People to be viewed or edited.
"""
# queryset = Person.objects.all().order_by('-created')
serializer_class = PersonSerializer
permission_classes = (DjangoModelPermissions, )
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
def get_queryset(self):
user = self.request.user
allowed_lists = get_objects_for_user(user, ('view_list'), klass=List)
queryset = set()
for lst in allowed_lists:
queryset.add(Person.objects.filter(member=lst))
return queryset
更新:感谢mehamasum。用最新的更新回溯(似乎与我的get_queryset覆盖更相关)
更新2:再次感谢mehamasum。现在,我的代码可以正常运行,但是我的测试用户仅对“列表1”具有视图访问权限,仍然可以将所有用户(甚至属于其他列表)都放在人员端点上。 -代码有什么问题吗?-
更新3:出现的 get_obejcts_for_user 函数未正确返回结果,如注释中提到的mehamasum一样。仍在寻找原因。
答案 0 :(得分:1)
由于未在basename
中为路由指定/app/really_simple_contact_management/urls.py
,因此引发了错误:
router.register(r'people', PersonViewSet)
来自docs:
basename-用于创建的URL名称的基础。如果未设置,则基名称将基于视图集的queryset属性自动生成(如果有)。请注意,如果视图集不包含queryset属性,则在注册视图集时必须设置基本名称。
将上面的行替换为:
router.register(r'people', PersonViewSet, base_name='people',)
根据您的喜好提供一个有意义的字符串作为base_name
,错误应该消失。
您正在手动构建并返回set
,但是get_queryset
函数期望实际的Django QuerySet。
您可以使用__in
operator重写函数:
def get_queryset(self):
user = self.request.user
allowed_lists = get_objects_for_user(user, ('view_list'), klass=List)
return Person.objects.filter(member__in=allowed_lists)