【问题标题】:Annotate with django-graphene and filters使用 django-graphene 和过滤器进行注释
【发布时间】:2018-02-24 18:07:25
【问题描述】:

我想在我的 django-graphene 解析器中使用 django-filter 对一个字段求​​和。通常我的解析器看起来像:

my_model = DjangoFilterConnectionField(
        MyModelNode,
        filterset_class=MyModelFilter)

def my_resolver(self, args, context, info):

    return MyModelFilter(
        data=format_query_args(args),
        queryset=self).qs

效果很好。
但是,我想为模型过滤器提供一个自定义查询集,以便我可以对字段执行聚合。我正在尝试做这样的事情:

def my_resolver(self, args, context, info):
    queryset = MyModel.objects.values(
        'customer_id').annotate(
        cost_amt=Sum('cost_amt', output_field=FloatField()))

    return MyModelFilter(
        data=format_query_args(args),
        queryset=queryset).qs

检查 GraphiQL 中的原始 SQL,它看起来是正确的。但是,我从 GraphQL 收到的错误消息是

"message": "Received incompatible instance \"{'cost_amt': 260.36, 'customer_id': 300968697}\"."

这是正确的结果,但我不确定 GraphQL 为何从 django-graphene 获取此对象。如何提供自定义查询集并使其工作?

【问题讨论】:

    标签: python django graphql


    【解决方案1】:

    要使查询集正常工作,您需要获取可以使用的模型实例

    queryset = MyModel.objects.annotate(cost_amt=Sum('cost_amt', output_field=FloatField()))
    

    然后您可以尝试进一步的操作。

    return MyModelFilter(data=format_query_args(args),queryset=queryset).qs
    

    还是错误

    尝试 ASSET UNION 看看是否可行,否则您也可以从relay.connection 尝试DjangoConnectionField

    【讨论】:

      【解决方案2】:

      看起来 django-graphene 需要一个模型实例的 QuerySet,当您在 QuerySet 上调用 .values() 时,您将返回一个字典查询集,因此是 Received incompatible instance

      您也许可以使用subquery expressions,或者做一些rawsql queries,这两者都会返回模型实例,这实际上取决于您在模型上设置的关系类型。

      看起来从关系的另一端(客户方)执行此注释可能更容易,因为您不需要使用.values(),但它可能无法满足您的需求。

      【讨论】:

      • 感谢您的回复。我在 .raw() 处进行了测试,但它返回了一个 RawQuerySet,django-graphene 和 django-filter 真的想要一个 QuerySet。它爆炸是因为 RawQuerySet 没有 .all() django-filter 尝试调用结果的方法。
      【解决方案3】:

      我认为您的问题出现是因为.values() 返回的是字典而不是模型实例。

      您可以尝试避免使用.values(),正如您在aggregation cheat sheetGenerate aggregates for each item in a QuerySet 部分的最后两个示例中所见:

      def my_resolver(self, args, context, info):
          queryset = MyModel.objects.annotate(
              cost_amt=Sum('cost_amt', output_field=FloatField()))
      
      return MyModelFilter(
          data=format_query_args(args),
          queryset=queryset).qs   
      

      但请记住,您必须相应地调整您的“前端”/接收器,因为现在您的解析器将返回查询集而不是字典。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-13
        • 2015-04-07
        • 2019-04-03
        • 2019-02-26
        • 2011-03-31
        • 2012-03-07
        • 2016-09-07
        • 2017-08-29
        相关资源
        最近更新 更多