Feature: Add DjangoInstanceField to allow reuse queryset on DjangoObjectType
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.
This looks like an alternative approach to #1112 ; I see a couple benefits with the approach here:
- Backwards compatible, developers opt-in by using a new field
- Does not duplicate querying
However, the approach in #1112 works with relay ids (if the DjangoObjectType opts into the relay interface), this does not.
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.
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.
@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.
We're going to want to add two unit tests:
- 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.
- Test that
get_nodeon the applicable DjangoObjectType is bypassed/not called. This is to test my assumption that we are not issuing a duplicate query.
@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
Hello @sebsasto ! Planning to update this PR?