[Fixed]-Enable PK based filtering in Django Graphene Relay while retaining Global IDs

4👍

I am not sure that you still want the answer or not, but at least let me try to answer to your question. Correct if my understanding is wrong. I just willing to help

Actually pk supposed to be DetailView not ListView that being used with filter.

requirements.txt

graphene-django==2.7.1
django==3.0.1
django-filter==2.2.0
python==3.8.1

models.py

from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()


class Objection(models.Model):
    detail = models.TextField(null=True, blank=True)
    hidden = models.BooleanField(default=False)
    report = models.BooleanField(default=False)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='objections',
                                   related_query_name='objection')

nodes.py

import django_filters
import graphene
from graphene import relay
from graphene_django import DjangoObjectType

from multy_herr.objections.models import Objection


class ObjectionFilter(django_filters.FilterSet):
    pk = django_filters.NumberFilter(field_name='pk')

    class Meta:
        model = Objection
        fields = [
            'pk',
        ]


class ObjectionNode(DjangoObjectType):
    pk = graphene.Field(type=graphene.Int, source='id')

    class Meta:
        model = Objection
        fields = [
            'id',
            'pk',
            'detail',
            'hidden',
            'report',
        ]
        filter_fields = {
            'pk': ['exact'],
            'detail': ['icontains', 'istartswith'],
            'created_by__name': ['icontains', ],
            'hidden': ['exact'],
            'report': ['exact'],
        }
        interfaces = (relay.Node,)


queries.py

import graphene
from graphene import relay
from graphene_django.filter import DjangoFilterConnectionField

from multy_herr.objections.grapheql.nodes import ObjectionNode, ObjectionFilter
from multy_herr.objections.models import Objection


class ObjectionQuery(graphene.ObjectType):
    objection = relay.Node.Field(ObjectionNode)
    all_objections = DjangoFilterConnectionField(ObjectionNode,
                                                 filterset_class=ObjectionFilter)

    def resolve_all_objections(self, info, **kwargs):
        if info.context.user.is_authenticated is False:
            return Objection.objects.none()
        return Objection.objects.filter(created_by=info.context.user)

I leave comment in query here for analogy. With my hackish solution Insomnia application will warns me with Unknown argument pk .... But works

query

query{
#   objection(id: "T2JqZWN0aW9uTm9kZTo1"){
#     id
#     report
#     hidden
#   }
  allObjections(pk: 5){
    edges{
      node{
        id
        pk
        hidden
        report
      }
    }
  }
}

response

{
  "data": {
    "allObjections": {
      "edges": [
        {
          "node": {
            "id": "T2JqZWN0aW9uTm9kZTo1",
            "pk": 5,
            "hidden": false,
            "report": false
          }
        }
      ]
    }
  }
}
👤joe

0👍

Have you tried solution 2 but with using id as the source instead?

class PKMixin(object):
    pk = graphene.Field(type=graphene.Int, source='id')

Also, if you’re only looking to fetch a single record, you shouldn’t go via a connection field anyway. You should define something like a batchByPk field on your schema instead.

A final thing to be aware of, is that at the current time graphene-django’s DjangoFilterConnectionField isn’t implemented in an efficient way, so you may not even want to use it anyway.

Leave a comment