Filter at multiple levels with GraphQL and Graphene

Question:

I’m using Django and Graphene and have multiple levels I’d like to filter on. But I can’t get past either “Unknown operation named “undefined”.” or getting ALL objects at each level of the hierarchy (i.e.: ALL jobDetails for all jobs listed for EACH job).

I’m trying to do this query:

query {
  allPushes(revision: "1ef73669e8fccac35b650ff81df1b575a39a0fd5") {
    edges {
      node {
        revision
        author
        jobs (result: "testfailed") {
          edges {
            node {
              result
              jobDetails (url_Iendswith: "errorsummary.log") {
                edges {
                  node {
                    url
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

In Django, jobDetails has a foreign key to jobs, which has a foreign key to pushes

My first attempt was to setup my nodes:

class JobDetailNode(DjangoObjectType):
    class Meta:
        model = JobDetail
        filter_fields = {
            'url': ('exact', 'icontains', 'iendswith')
        }
        interfaces = (relay.Node, )


class JobNode(DjangoObjectType):
    class Meta:
        model = Job
        filter_fields = ('result', 'tier')
        interfaces = (relay.Node, )

    job_details = DjangoFilterConnectionField(JobDetailNode)


class PushNode(DjangoObjectType):
    class Meta:
        model = Push
        filter_fields = ('revision', )
        interfaces = (relay.Node, )

    jobs = DjangoFilterConnectionField(JobNode)

But this returns, as I said, all jobDetails at for EACH job, not just the jobDetails that belong to that job.

But if I remove those DjangoFilterConnectionField fields, then I can’t filter at each level; just the first.

My Query looks like this:

class Query(ObjectType):
    all_pushes = DjangoFilterConnectionField(PushNode)
    all_jobs = DjangoFilterConnectionField(JobNode)
    all_job_details = DjangoFilterConnectionField(JobDetailNode)

    def resolve_all_pushes(self, args):
        return Push.objects.filter(**args)

    def resolve_all_jobs(self, args):
        return Job.objects.filter(**args)

    def resolve_all_job_details(self, args):
        return JobDetail.objects.filter(**args)

Any suggestions on how to setup filtering at multiple levels like this? Thanks in advance!!

Asked By: Cameron

||

Answers:

This is a bug in graphene-django. It was fixed in version 1.3.
Changelog

Regards.

Answered By: Julián Cortés

I’m not sure if the same person asked the question on graphene github page, but it looks almost, if not exactly the same. Apart from the fact mentioned bug existed, you still need some improvement in your code.

In order to make it work as you described (getting only related JobDetail for each Job) you have to define a resolver inside JobNode:

def resolve_job_details(self, args, context, info):
    return JobDetail.objects.filter(job=self, **args)

Of course you need also Job resolver inside PushNode:

def resolve_jobs(self, args, context, info):
    return Job.objects.filter(push=self, **args)
Answered By: Jacu
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.