question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Extend resolution system for deriving a DjangoObjectType from a django model

See original GitHub issue

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

The assumption of this package is that there is only ever 1 DjangoObjectType subclass for each Django model. A pretty common counterexample is when I have a Profile model with a profile photo on it as well as a phone number, address, and misc other private information.

In public contexts, I would want to show a limited subset of these fields. Perhaps we would define it with

class ProfilePublicNode(DjangoObjectType):
    class Meta:
        model = Profile
        fields = ["username", "profile_photo"]

Meanwhile, there are situations where I would want to show the entire set of fields, such as when allowing a user to update their own profile.

Example:

class ProfilePrivateNode(DjangoObjectType):
    class Meta:
        model = Profile
        fields = list(ProfileNode._meta.fields.keys()) + ["phone_number", "other_secret_stuff"]

This is well and good. WE CAN DO THIS.

Where we have problems is when I have another object where I want to nest a public or private node like this.

Say:

class ArticleNode(DjangoObjectType):
    class Meta:
        model = Article
        fields = ["title", "body_text", "author"]

…where author is a Profile model. I have no control over whether ProfilePublicNode or ProfilePrivateNode is used. I just get whichever one is defined last in the file.

Currently, graphene-django populates the registry (https://github.com/graphql-python/graphene-django/blob/main/graphene_django/registry.py) each time a subclass of DjangoObjectType is defined: https://github.com/graphql-python/graphene-django/blob/main/graphene_django/types.py#L275

The registry is implemented as a dictionary where they key is the django model and the value is the DjangoObjectType subclass. It only has the ability to store one graphene type per django model. And so the type which is defined last is the type that wins.

This is reenforced by the dead code assertion here which has survived since the initial commit: https://github.com/graphql-python/graphene-django/blob/main/graphene_django/registry.py#L15-L17

This is really not ideal for reasons:

  • it makes distinctions like public/private fields implicit, not explicit
  • it does not give sufficient control over resolution of nested objects

Describe the solution you’d like

While preserving the existing automatic registry magic for backwards compatibility, I would like to allow the DjangoObjectType subclass to explicitly specify the desired DjangoObjectType subclass for its nested related objects.

Describe alternatives you’ve considered

  • Strawberry (just discovered today, looks neat, a little bare bones Flask-esque for my feature-building urgency)
  • Crying.
  • Moving to Siberia and tending to a flock of Yaks, never to see a computer again

Additional context

N/A

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7

github_iconTop GitHub Comments

1reaction
kevindicecommented, Mar 8, 2021

Thanks for your help - will send over a docs PR soon to add a note to this effect.

1reaction
kevindicecommented, Mar 8, 2021

Well, while this has been equally enlightening and embarrassing, I guess the one thing that could be added now is an opt-in STRICT_MODE where all node relations must be explicitly defined for safety so that the auto-registry goes unused. Also, a mechanism to perform resolutions for cyclic graphs based on strings - assuming that’s not already supported.

Read more comments on GitHub >

github_iconTop Results From Across the Web

`DjangoObjectType` using the same django model do not ...
May 24, 2020: Issue DjangoObjectType duplicate models breaks Relay node resolution #971 posted just linking a complete description.
Read more >
Models - Django documentation
Each model is a Python class that subclasses django.db.models. ... myapp_person , is automatically derived from some model metadata but can be overridden....
Read more >
Graphene Documentation - Read the Docs
To create GraphQL types for each of our Django models, we are going to subclass the DjangoObjectType class which will automatically define ...
Read more >
Is there a way to elegantly use a django model as an input ...
Say I have, class PersonNode(DjangoObjectType): class Meta: model = Person fields = ('first_name' ...
Read more >
Queries & ObjectTypes - Graphene-Python
Specifying which fields to include¶. By default, DjangoObjectType will present all fields on a Model through GraphQL. If you only want a subset...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found