DJango 休息框架 - API 使用来自相关模型的过滤器字段的列表

DJango rest framework - API list using filter field from related models

您好,我是 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 中有我可以阅读的内容,我会尝试查看过滤和查询集,但我无法找到任何可以开箱即用的东西

我也是 Whosebug 的新手,我试图用尽可能多的相关信息来使我的问题简短,所以如果有任何遗漏,我很乐意编辑我的问题

试试这个:

{{baseUrl}}/engine/service?network__forwarded_port=8080

可能有用。

文档:https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships-1

编辑:

如果上面的回答不行,你可以修改ServiceApi class 自己过滤:

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__'

我能够使用以下查询集覆盖解决这个问题

    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 的经验,所以我不确定这可能会带来什么样的错误,但它是一种对我有用的 hack。如果我发现这真的很糟糕,我会回来删除它。