【问题标题】:Filtering nested resources Django REST Framework过滤嵌套资源 Django REST Framework
【发布时间】:2017-10-19 21:17:16
【问题描述】:

一开始我想说我找到了我的问题的部分答案 (How can I apply a filter to a nested resource in Django REST framework?),但它并没有 100% 涵盖我的问题。

我已经嵌套了 3 个模型:

- 模型A

-- 模型AB

---- 型号B

我需要通过 ModelB 过滤所有 ModelA,但我还需要过滤 ModelB。

例如。 /modelA?modelab__modelb__id=100

需要返回值:

[{id:1,
    modelab: [{
        id:10
        modelb{
          id: 100
        }]
    }]
}]

但它会返回

[{id:1,
    modelab: [{
        id:10
        modelb{
          id: 100
        },
        id:11
        modelb{
          id: 102
        }]
    }]
}]

所以它只过滤第一级嵌套。我希望将应用的过滤器应用于所有嵌套模型。

我的代码:

// models.py
class ModelA(models.Model):
    name = models.TextField()
class ModelB(models.Model):
    name = models.TextField()
class ModelAB(models.Model):
    modelA = models.ForeignKey(ModelA)
    modelB = models.ForeignKey(ModelB)
    type_id = models.IntegerField(default=0)

// views.py
class ModelAFilter(filters.FilterSet):

    vacancy_id = Filter(name="vacancy__id")
    class Meta:
        model = Candidate
        fields = ('name', 'modelAB__modelB__name')

class ModelAViewSet(viewsets.ModelViewSet):
    queryset = ModelA.objects.all()
    serializer_class = ModelASerializer

    filter_backends = (filters.DjangoFilterBackend, )
    filter_class = ModelFilter

// serializers.py
class ModelBSerializer(serializers.ModelSerializer):

    modelB = ModelB(many=True)

    class Meta:
        model = ModelB
        fields = ('id', 'name')

class ModelABSerializer(serializers.ModelSerializer):

    modelB= ModelBSerializer(many=True)

    class Meta:
        model = ModelB
        fields = ('id', 'name', 'modelB',)

class ModelASerializer(serializers.ModelSerializer):

    modelAB = ModelAB(many=True)

    class Meta:
        model = ModelA
        fields = ('id', 'name', 'modelAB')

【问题讨论】:

  • 添加你在问题中使用的代码
  • 添加代码和更改命名

标签: django django-rest-framework django-filter


【解决方案1】:

您必须在视图集上覆盖 get_queryset 方法并过滤 prefetch_related 查询:

def get_queryset(self):
    # get the filter value
    modelb_id = self.request.query_params.get('modelab__modelb__id', None)
    queryset_modelab = ModelAB.objects.all()
    # you can use django-filter class here too
    if modelb_id:
        queryset_modelab = queryset_modelab.filter(modelb_id=modelb_id)
    queryset_modelab.select_related('modelb')
    queryset = (ModelA.objects
                .prefetch_related(
                    Prefetch('modelab_set', queryset=queryset_modelab))
                .all())
    # modela filter class will work on this queryset
    return queryset

【讨论】:

  • 我在想,但是什么时候它没有过滤器或者什么时候会有更多的字段来过滤?我需要检查它们是否存在......我在想是否有任何动态的方式来做到这一点。在 SQLAlchemy 中,我可以使用 eager_loading
  • 是的,您肯定需要检查过滤器是否存在。为了更清楚,我会稍微编辑一下答案。
猜你喜欢
  • 2014-12-15
  • 2015-09-21
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 2015-01-10
  • 2019-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多