Модификация набора запросов ModelViewSet для запроса много-многих отношений на основе разрешений django-guardian - PullRequest
0 голосов
/ 03 марта 2019

У меня есть 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 упоминается в комментариях.Все еще ищу причину.

1 Ответ

0 голосов
/ 03 марта 2019

Похоже, что ваша ошибка выдается, потому что вы не указали basename для своего маршрута в /app/really_simple_contact_management/urls.py:

router.register(r'people', PersonViewSet)

Из документов :

basename - база, используемая для созданных имен URL.Если не задано, базовое имя будет автоматически сгенерировано на основе атрибута набора запросов в наборе, если таковое имеется.Обратите внимание, что если набор представлений не включает атрибут набора запросов, то при регистрации набора вы должны установить базовое имя.

Замените строку выше на:

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)
...