Как фильтровать запрос по нескольким значениям, используя DRF, djagno-filters и значения HyperlinkedIdentityField

Основная цель является получение набора запросов на основе нескольких значений в запросе.

Бизнес-логика заключается в получении всех контрактов для нескольких водителей.

Пример: запрос url:

/api/contract/?driver=http://localhost:8000/api/driver/1,http://localhost:8000/api/driver/2

В ответе должны быть все контракты для этих двух водителей.

Сериализатор драйвера:

class DriverSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(
        view_name='driver-detail',
        read_only=True
    )

    class Meta:
        model = Driver
        fields = [
            'url',
            'id',
            'first_name',
            'last_name',
        ]

Contract serializer:

class ContractSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(
        view_name='contract-detail',
        read_only=True
    )
    driver = serializers.StringRelatedField(many=False)

    class Meta:
        model = Contract
        fields = [
            'url',
            'id',
            'contract_detail_fields',
            'driver',
        ]

Просмотр договора

class ContractViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.ContractSerializer
    queryset = Contract.objects.all()
    permission_classes = (IsAuthenticated,)
    filter_backends = [DjangoFilterBackend]
    filterset_class = ContractFilter

ContractFilter:

class ContractFilter(FilterSet):
    driver = CustomHyperlinkedIdentityFilterList('driver')

Что я пробовал, так это сделать пользовательский filterField на основе ответа by Sherpa

class CustomHyperlinkedIdentityFilterList(django_filters.BaseCSVFilter, 
                                                 django_filters.CharFilter):
    def filter(self, qs, value):
        values = value or []
        for value in values:
            qs = super(CustomHyperlinkedIdentityFilterList,
                       self).filter(qs, value)
        return qs

Ответ ValueError: Поле 'id' ожидало число, но получило 'http://localhost:8000/api/drivers/driver/3/'.

Затем я пытаюсь изменить фильтрацию по id, а не по urlField и изменяю эту строку

qs = super(CustomHyperlinkedIdentityFilterList, self).filter(qs, value)

на это:

qs = super(CustomHyperlinkedIdentityFilterList, self).filter(qs, get_id_from_url(value))

где get_id_from_url это:

def get_id_from_url(url):
    return int(resolve(urlparse(unquote(url)).path).kwargs.get('pk'))

Но он возвращает мне только контракты для последнего водителя, а не для обоих.

Тогда я также попробовал конфигурации, основанные на ответе Славы

class ContractFilter(FilterSet):
  
    class Meta:
        model = Contract
        fields = ['driver']

при использовании этого решения ответом будет Bad request {"driver":["Выберите правильный выбор. Этот выбор не является одним из доступных вариантов."]}

Надеюсь, есть очень простые решения, которые я упустил.

Вернуться на верх