Django Rest Framework: фильтрация отношений с использованием гиперссылок URI - PullRequest
0 голосов
/ 12 марта 2020

Я использую Django Rest Framework для создания простого API. У меня есть две модели с отношением внешнего ключа:

class Article(models.Model):
    publisher = models.ForeignKey('Publisher', ...)

class Publisher(models.Model):
    name = ...

Я сериализую их, используя идентификаторы гиперссылок:

{
  "url": "http://localhost:8000/api/1/article/1",
  "publisher": {
    "url": "http://localhost:8000/api/1/publisher/1",
    "name": "Publisher One"
  },
  ...
}

Я хотел бы отфильтровать все статьи по отношению к издателю спецификации. c статья, в идеале что-то вроде этого:

http://localhost:8000/api/1/article?publisher=http://localhost:8000/api/1/publisher/1

Я попытался создать пользовательский FilterClass, однако url не является действительным полем в модели, поэтому я не уверен, как сослаться на него.

Если я извлечу id из URL-адреса и передам, что он работает, как и ожидалось, но я бы предпочел, чтобы клиенту не нужно было знать, как анализировать гиперссылочный идентификатор для «реального» идентификатор.

Я также могу добавить id к сериализатору, но если это решение, то какой смысл в HyperlinkedModelSerializer?

1 Ответ

0 голосов
/ 12 марта 2020

Я придумал альтернативный подход, используя drf ViewSet действия. Вместо того чтобы использовать Publisher URI для фильтрации конечной точки Article, я добавил настраиваемое действие в представление издателя, чтобы вернуть соответствующие статьи:

class PublisherViewSet(base.ReadOnlyModelViewSet):
    queryset = models.Publisher.objects.order_by('name')
    ...

    @action(methods=['get'], detail=True)
    def unclaimed(self, request, pk=None):
        serializer = ArticleFieldSerializer(context={'request': request})
        unclaimed = models.Article.objects.unfinished().filter(publisher=pk)
        return Response(
            [serializer.to_representation(article) for article in unclaimed]
        )

Не требуется синтаксический анализ URI, я просто необходимо добавить к нему действие и GET.

Возможность фильтрации по URI была бы намного более гибкой, но это работает.

...