Automatic object type field for reverse one-to-one model fields cannot resolve when model field has `related_query_name` and object type has custom `get_queryset`
MrThearMan opened this issue · comments
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
Related
model fieldexample
is aOneToOneField
, which has defined arelated_query_name
different from the field'srelated_name
. -
The
RelatedType
ObjectType defined theget_queryset
class 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_name
s instead of related_name
s.
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