Cameron
Cameron

Reputation: 1000

Filter at multiple levels with GraphQL and Graphene

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!!

Upvotes: 1

Views: 1589

Answers (2)

Jacu
Jacu

Reputation: 61

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)

Upvotes: 0

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

Regards.

Upvotes: 2

Related Questions