Search code examples
pythondjangographene-python

Self-referencing class variable in Python


I'm trying to implement a folder-like type in Graphene-Django. A folder can contain files or folders. Doing this:

Django model:

from django.db import models
class Folder(models.Model):
    name = models.CharField(...)
    parent = models.ForeignKey('self')

class File(models.Model):
    name = models.CharField(...)
    content = models.TextField(...)

Graphene API:

from files.models import Folder, File

class FolderNode(DjangoObjectType):
    folders = graphene.List(FolderNode)

    def resolve_folders(self, args, context, info):
        return Folder.objects.filter(parent=self)

    class Meta:
        model = Folder

fails, because I can't refer to FolderNode in its own class definition. Applying the answer to another question:

class FolderNode(DjangoObjectType):
    def __new__(cls, *args, **kwargs):
        cls.folders = graphene.List(cls)
        return object.__new__(cls, *args, **kwargs)

    def resolve_folders(self, args, context, info):
        return Folder.objects.filter(parent=self)

    class Meta:
        model = Folder

doesn't work either, because Graphene only sees class variables that are part of the declaration in deciding what to add to the API. Any ideas?


Solution

  • Based on https://github.com/graphql-python/graphene/issues/110, the correct way to do this is with a string:

    class FolderNode(DjangoObjectType):
        folders = graphene.List('FolderNode')