Джанго ОТДЫХ; используйте queryset на множестве многих полей для фильтрации этого связанного поля - PullRequest
0 голосов
/ 10 мая 2019

Я использую инфраструктуру Django REST и не могу понять, как отфильтровать результаты подполя (многозначного поля), которое возвращается, когда запрашивается ссылочная модель / представление.

У меня есть модель тега, котораясвязанные с моделью книги через много полей.При запросе тегов он возвращает всю книгу, связанную с ним.Однако мне нужно отфильтровать книги, чтобы они включали только те книги, к которым у текущего пользователя есть доступ.

I может правильно отфильтровать это в виде книги, но не могу понять, какзаставить это работать для представления тегов

// Book model:
class BookQuerySet(models.QuerySet):
    def visible_to(self, user):
        if user.can_see_secrets:
            return self
        return self.exclude(secret_book=True)


class Book(models.Model):
    id = models.AutoField(db_column='Id', primary_key=True)
    name = models.CharField(db_column='CatalogNumber', unique=True, max_length=50)
    secret_book = models.IntegerField(db_column='secret', default=False)
    objects = BookQuerySet.as_manager()

    class Meta:
        managed = False
        db_table = 'book'
        app_label = 'core'


// Book view:
class BooksFilteringBackend(filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        current_user = request.user
        queryset = queryset.visible_to(current_user)
        return queryset

class BookViewSet(viewsets.ReadOnlyModelViewSet):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    queryset = Book.objects.all()
    filter_backends = (BooksFilteringBackend,)
    serializer_class = BookSerializer

There is a BookSerializer that doesnt do anything interesting

Теперь вышесказанное работает, если пользователь запрашивает представление книги, он получает только те книги, которые должен видеть.

Вот моя проблема:

// Tag model
class Tag(models.Model):
    id = models.AutoField(db_column='Id', primary_key=True)
    description = models.CharField(db_column='Description', unique=True, max_length=255)
    books = models.ManyToManyField('core.Book', through='BookTag', related_name='tags')

    class Meta:
        managed = False
        db_table = 'tag'
        app_label = 'tags'

// Tag viewset
class TagViewSet(viewsets.ReadOnlyModelViewSet):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    queryset = Tag.objects.all()
    serializer_class = TagSerializer

// Tag serializer
class TagSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()
    description = serializers.CharField(max_length=255)
    books = BookSerializer(many=True, read_only=True)

    class Meta:
        model = Tag
        fields = ('id',
                  'description',
                  'books',)

Если я коснусь набора просмотра тега, я получу все книги, связанные с тегом, потому что я не фильтрую книги на основе той же логики, описанной выше.Как сделать так, чтобы при извлечении тегов я мог использовать BookQuerySet или что-то подобное.

Цените любые идеи!

1 Ответ

0 голосов
/ 10 мая 2019

Нашел ответ: Как вы фильтруете вложенный сериализатор в Django Rest Framework?

Хитрость заключается в том, чтобы сделать это на уровне сериализатора.Очевидно, что когда сериализатор тегов ссылается на сериализатор книг, запрос для книг - это все (), так что вы можете переопределить это:

В моем неинтересном файле сериализатора книг:

// added:
class BookFilteredListSerializer(serializers.ListSerializer):
    def to_representation(self, data):
        data = data.visible_to(self.context['request'].user)
        return super(BookFilteredListSerializer, self).to_representation(data)

// And then reference this from the actual BookSerializer meta:
class WorkSerializer(serializers.ModelSerializer):

     ...

     class Meta:
         model = Work
         list_serializer_class = WorkFilteredListSerializer
         fields = (...)

Теперь тегиспользует эту систему фильтрации, когда я запрашиваю конечную точку тега, и она загружается в процессе работы.

...