graphql-python / graphql-python/graphene-django

Feature Request: DjangoInterface

Open
#1,366 2 comments 1 reaction 0 assignees View on GitHub
✨enhancement
Dominant language
Python
Stars
4.4k
Forks
760
PR merge metrics
No merged PRs in 30d

Description

**Is your feature request related to a problem? Please describe.**

One of the main benefits of `graphene_django` is the de-duplication in field types and descriptions for model fields. However, it's common to have polymorphic models, which are more well suited to GraphQL interfaces. For example, the shape of a JSON field could vary depending on a `type` field.

There doesn't seem to be a good way to import model field info into interfaces like there is for ObjectTypes at the moment.

**Describe the solution you'd like**

It would be great if there was a `DjangoInterface` class which could be used for defining interfaces similarly to `DjangoObjectType`. This would allow for the following:

```py
class Person(DjangoInterface):
class Meta:
model = PersonModel
fields = ("id", "name", "birthday")

@classmethod
def resolve_type(cls, instance, info):
return Employee if instance.employer else BasePerson

class BasePerson(DjangoObjectType):
class Meta:
model = PersonModel
interfaces = (Person,)

class Employee(DjangoObjectType):
class Meta:
model = PersonModel
fields = ("job_title")
interfaces = (Person,)

company = NonNull(String)

def resolve_company(root, info):
return root.employer.name
```

In this case, `Employee` would have the fields id, name, birthday, job_title, and company. `BasePerson` would have only id, name, and birthday.

**Describe alternatives you've considered**

Another option would be to tie all implementations of an interface to the same Django model. But using the model only to generate the field definitions and keeping the `DjangoObjectType` interface the same seems both simpler and more flexible.

Right now, the closest approach seems to be something like:

```py
class MyInterface(graphene.Interface):
my_field = convert_django_field(MyModel.my_field.field)
```

This works okay but is pretty hacky, relying on private interfaces and not working for relation fields.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.