Skip to content

Commit ea48e20

Browse files
committed
fix: reference field, cache field refetching data even when field is already pre-fetched
1 parent a577209 commit ea48e20

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

graphene_mongo/converter.py

+34-14
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ def convert_field_to_dynamic(field, registry=None, executor: ExecutorEnum = Exec
545545
model = field.document_type
546546

547547
def reference_resolver(root, *args, **kwargs):
548-
document = getattr(root, field.name or field.db_name)
548+
document = root._data.get(field.name or field.db_name, None)
549549
if document:
550550
queried_fields = list()
551551
_type = registry.get_type_for_model(field.document_type, executor=executor)
@@ -558,16 +558,23 @@ def reference_resolver(root, *args, **kwargs):
558558
item = to_snake_case(each)
559559
if item in field.document_type._fields_ordered + tuple(filter_args):
560560
queried_fields.append(item)
561+
562+
fields_to_fetch = set(list(_type._meta.required_fields) + queried_fields)
563+
if isinstance(document, field.document_type) and all(
564+
document._data[_field] is not None for _field in fields_to_fetch
565+
):
566+
return document # Data is already fetched
561567
return (
562568
field.document_type.objects()
563569
.no_dereference()
564-
.only(*(set(list(_type._meta.required_fields) + queried_fields)))
570+
.only(*fields_to_fetch)
565571
.get(pk=document.id)
566572
)
567573
return None
568574

569575
def cached_reference_resolver(root, *args, **kwargs):
570-
if field:
576+
document = root._data.get(field.name or field.db_name, None)
577+
if document:
571578
queried_fields = list()
572579
_type = registry.get_type_for_model(field.document_type, executor=executor)
573580
filter_args = list()
@@ -579,16 +586,22 @@ def cached_reference_resolver(root, *args, **kwargs):
579586
item = to_snake_case(each)
580587
if item in field.document_type._fields_ordered + tuple(filter_args):
581588
queried_fields.append(item)
589+
590+
fields_to_fetch = set(list(_type._meta.required_fields) + queried_fields)
591+
if isinstance(document, field.document_type) and all(
592+
document._data[_field] is not None for _field in fields_to_fetch
593+
):
594+
return document # Data is already fetched
582595
return (
583596
field.document_type.objects()
584597
.no_dereference()
585-
.only(*(set(list(_type._meta.required_fields) + queried_fields)))
598+
.only(*fields_to_fetch)
586599
.get(pk=getattr(root, field.name or field.db_name))
587600
)
588601
return None
589602

590603
async def reference_resolver_async(root, *args, **kwargs):
591-
document = getattr(root, field.name or field.db_name)
604+
document = root._data.get(field.name or field.db_name, None)
592605
if document:
593606
queried_fields = list()
594607
_type = registry.get_type_for_model(field.document_type, executor=executor)
@@ -601,16 +614,20 @@ async def reference_resolver_async(root, *args, **kwargs):
601614
item = to_snake_case(each)
602615
if item in field.document_type._fields_ordered + tuple(filter_args):
603616
queried_fields.append(item)
617+
618+
fields_to_fetch = set(list(_type._meta.required_fields) + queried_fields)
619+
if isinstance(document, field.document_type) and all(
620+
document._data[_field] is not None for _field in fields_to_fetch
621+
):
622+
return document # Data is already fetched
604623
return await sync_to_async(
605-
field.document_type.objects()
606-
.no_dereference()
607-
.only(*(set(list(_type._meta.required_fields) + queried_fields)))
608-
.get
624+
field.document_type.objects().no_dereference().only(*fields_to_fetch).get
609625
)(pk=document.id)
610626
return None
611627

612628
async def cached_reference_resolver_async(root, *args, **kwargs):
613-
if field:
629+
document = root._data.get(field.name or field.db_name, None)
630+
if document:
614631
queried_fields = list()
615632
_type = registry.get_type_for_model(field.document_type, executor=executor)
616633
filter_args = list()
@@ -622,11 +639,14 @@ async def cached_reference_resolver_async(root, *args, **kwargs):
622639
item = to_snake_case(each)
623640
if item in field.document_type._fields_ordered + tuple(filter_args):
624641
queried_fields.append(item)
642+
643+
fields_to_fetch = set(list(_type._meta.required_fields) + queried_fields)
644+
if isinstance(document, field.document_type) and all(
645+
document._data[_field] is not None for _field in fields_to_fetch
646+
):
647+
return document # Data is already fetched
625648
return await sync_to_async(
626-
field.document_type.objects()
627-
.no_dereference()
628-
.only(*(set(list(_type._meta.required_fields) + queried_fields)))
629-
.get
649+
field.document_type.objects().no_dereference().only(*fields_to_fetch).get
630650
)(pk=getattr(root, field.name or field.db_name))
631651
return None
632652

0 commit comments

Comments
 (0)