DJango rest framework - список API с использованием поля фильтра из связанных моделей
Здравствуйте, я новичок в Django и фреймворке Django rest, поэтому моя терминология может быть ошибочной.
Я пытаюсь создать API, который возвращает список элементов из модели, но отфильтрованный на основе полей другой связанной модели.
Я предоставлю свои текущие классы представления и сериализатора, а также модели
class service(models.Model):
name = models.CharField(max_length=50)
vendor = models.CharField(max_length=50)
version = models.CharField(max_length=10)
registration_status = models.BooleanField(default=False)
class service_network(models.Model):
service = models.OneToOneField(
service,
related_name='network',
on_delete=models.CASCADE,
primary_key=True,
)
forwarded_port = models.CharField(max_length=50)
class ServiceNetworkSerializer(serializers.ModelSerializer):
class Meta:
model = service_network
fields = '__all__'
class ServiceSerializer(serializers.ModelSerializer):
network = ServiceNetworkSerializer()
class Meta:
model = service
fields = [
'id',
'name',
'vendor',
'version',
'registration_status',
'network',
]
class ServiceAPI(ModelViewSet):
queryset = service.objects.all()
serializer_class = ServiceSerializer
filterset_fields = '__all__'
В настоящее время я могу получить списки, используя строку запроса URL
{{baseUrl}}/engine/service?registration_status=true
Что я хочу сделать, это что-то вроде этого
{{baseUrl}}/engine/service/network?forwarded_port=8080
Я бы ожидал получить список сервисов, где связанное сетевое поле "forwarded_port" равно 8080.
Есть ли другой способ запросить этот API? Может быть, используя POST с телом, содержащим запрос? Если есть что-то в DOCS, что я могу прочитать, я пытался просмотреть фильтрацию и наборы запросов, но я не смог найти ничего, что могло бы сделать это из коробки
Я тоже новичок на stackoverflow и постарался сделать свой вопрос кратким и с максимальным количеством нужной информации, так что если чего-то не хватает, я буду рад отредактировать свой вопрос
Попробуйте это:
{{baseUrl}}/engine/service?network__forwarded_port=8080
Возможно, это работает.
Док: https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships-1
РЕДАКТИРОВАНИЕ:
Если ответ выше не работает, вы можете изменить класс ServiceApi и фильтровать самостоятельно:
class ServiceAPI(ModelViewSet):
def get_queryset(self):
if self.request.GET.get(network__forwarded_port)
return service.objects.filter(network__forwarded_port = self.request.GET.get(network__forwarded_port))
else:
return service.objects.all()
serializer_class = ServiceSerializer
filterset_fields = '__all__'
Я смог решить эту проблему, используя следующий queryset override
def get_queryset(self):
if len(self.request.GET) > 0:
query_set = {}
for query in self.request.GET:
query_set[query] = self.request.GET.get(query)
return service.objects.filter(**query_set)
else:
return service.objects.all()
Это позволяет вам фильтровать поля без явного указания того, что это такое, в случаях, когда у вас много полей, которые нужно фильтровать. Я также должен сказать, что поскольку у меня нет опыта работы с Django, я не уверен, какие ошибки это может вызвать, но это хак, который сработал для меня. Если я обнаружу, что это действительно плохо, я вернусь и удалю это.