-
Notifications
You must be signed in to change notification settings - Fork 766
Description
What is the current behavior?
Given the following models:
from django.db import models
class Example(models.Model):
pass
class Related(models.Model):
example = models.OneToOneField(
Example,
on_delete=models.CASCADE,
related_name="related",
# Important!
related_query_name="related_item",
)... and the following ObjectTypes:
import graphene
from graphene_django import DjangoObjectType
from graphene_django.fields import DjangoConnectionField
class ExampleType(DjangoObjectType):
class Meta:
model = Example
fields = [
"id",
"related",
]
connection_class = graphene.Connection
interfaces = (graphene.relay.Node,)
class RelatedType(DjangoObjectType):
class Meta:
model = Related
fields = [
"id",
"example",
]
connection_class = graphene.Connection
interfaces = (graphene.relay.Node,)
# Important!
@classmethod
def get_queryset(cls, queryset, info):
return queryset... and the following query definitions:
import graphene
from graphene_django.fields import DjangoConnectionField
class Query(graphene.ObjectType):
examples = DjangoConnectionField(ExampleType)
related = DjangoConnectionField(RelatedType)Now, trying to query like this:
query {
examples {
edges {
node {
id
related {
id
}
}
}
}
}... will result in an error like this:
[
{
"locations": [
{
"column": 9,
"line": 3,
},
],
"message": "Example has no field named 'related'",
"path": [
"examples",
"edges",
0,
"node",
"related",
],
}
]What causes the current behavior?
This happens because of two things:
-
The
Relatedmodel fieldexampleis aOneToOneField, which has defined arelated_query_namedifferent from the field'srelated_name. -
The
RelatedTypeObjectType defined theget_querysetclass method.
When graphene_django.converter.convert_onetoone_field_to_djangomodel creates a the ObjectType for the ExampleType field related, it uses the RelatedType ObjectType's queryset for this check: graphene_django.converter.py:283
Since the RelatedType's get_queryset was modified, this check does not early return, thus we use the custom_resolver below that.
When custom_resolver resolves, it tries to fetch reversed_field_name from the class fields (uses django.db.models.options.py:649). Since related is a reverse relation, it does not exist in _forward_fields_map. However, it's not found from fields_map either, since the keys in fields_map use fields' related_query_names instead of related_names.
Therefore, automatic field object type creation fails in this case (reverse one-to-one fields with get_queryset defined).
What is the expected behavior?
I should be able to make the query described above with the given object type configuration.
What is the motivation / use case for changing the behavior?
I should be able to rely on automatic field generaton for reverse one-to-one relations with related_query_name to object types that have defined get_queryset. This reduces boilerplate code, since otherwise I would need to define the field and resolver manually.
Please tell us about your environment:
- Version: v3.1.5
- Platform: Windows 11