Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add DjangoInstanceField to allow reuse queryset on DjangoObjectType #1133

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

sebsasto
Copy link
Contributor

There are some scenarios in which you want to use the queryset inside DjangoObjectType as a pre-filter to return a single object.

In these cases you might not want to do the whole check again in the resolver to do the filtering of the queryset. This new Field allow to use the DjangoObjectType queryset inside the resolver.

Example:

class UserType(DjangoObjectType):
    
    @classmethod
    def get_queryset(cls, queryset, info):
        return queryset.filter(is_active=True)

class Query(graphene.ObjectType):
    user_by_id = DjangoInstanceField(UserType, id=graphene.Int(required=True), unique_fields=('id',))

In this case will try to get the object that is_active and have the id.

Example 2:

class UserType(DjangoObjectType):
    
    @classmethod
    def get_queryset(cls, queryset, info):
        return queryset.filter(is_active=True)

class Query(graphene.ObjectType):
    user_by_id = DjangoInstanceField(UserType, unique_field=graphene.Int(required=True), unique_fields=('unique_field',))

    resolve_user_by_id(parent, info, **args):
        return User.objects.filter(is_super_user = True)

In this case the object there will be 2 filters in the queryset and then if will try to get the instance with the unique_field.

@zbyte64
Copy link
Collaborator

zbyte64 commented Feb 22, 2021

This looks like an alternative approach to #1112 ; I see a couple benefits with the approach here:

  1. Backwards compatible, developers opt-in by using a new field
  2. Does not duplicate querying

However, the approach in #1112 works with relay ids (if the DjangoObjectType opts into the relay interface), this does not.

@sebsasto
Copy link
Contributor Author

Hello @zbyte64
I will try to copy the test cases of #1112 and adapt the solution to also use relay ids. I think is doable.

@sebsasto
Copy link
Contributor Author

Hello @zbyte64 can you have a look, please? It passes all the tests from #1112 and we are not doing the extra query in the resolver when it is a FK. It also works with relay ids.

@sebsasto sebsasto force-pushed the instance-field branch 2 times, most recently from 0e46aa7 to fbdc10f Compare February 23, 2021 18:09
@sebsasto
Copy link
Contributor Author

@zbyte64 I also unified the OneToOneRel field to use the DjangoInstance. In this case we will need to make the extra query because Django does provide the ID of the reverse relation. Please let me know what do you think.

I'm using this approach in my project and it is working so far well.

else:
description = get_django_field_description(field)

return DjangoInstanceField(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we also lookup the primary field of the model and pass the result in as unique_fields? I could see a model having a different primary key field name and I think that would cause this to break

@zbyte64
Copy link
Collaborator

zbyte64 commented Mar 3, 2021

We're going to want to add two unit tests:

  1. A scenario that explicitly uses a relay global id as input. I see that our tests are using this with object types that have the relay interface but it doesn't seem we pass in a relay id in the tests.
  2. Test that get_node on the applicable DjangoObjectType is bypassed/not called. This is to test my assumption that we are not issuing a duplicate query.

@sebsasto
Copy link
Contributor Author

sebsasto commented Mar 3, 2021

@zbyte64 I will have to add some extra code that I did before addressing some issues with some variables names but I’ll be able to do it next week

@firaskafri
Copy link
Collaborator

Hello @sebsasto ! Planning to update this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants