Skip to content

Commit 924dc2a

Browse files
committed
fetch deferred attrs
1 parent c01152a commit 924dc2a

File tree

1 file changed

+36
-9
lines changed

1 file changed

+36
-9
lines changed

src/django_idom/hooks.py

+36-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
from __future__ import annotations
22

3-
from dataclasses import dataclass
43
from threading import Thread
54
from types import FunctionType
65
from typing import (
7-
Dict,
86
Type,
97
Union,
108
Any,
11-
Awaitable,
129
Callable,
1310
DefaultDict,
14-
Optional,
1511
Sequence,
1612
Type,
1713
Union,
@@ -20,6 +16,8 @@
2016
NamedTuple,
2117
)
2218

19+
from django.db.models.base import Model
20+
from django.db.models.query import QuerySet
2321
from typing_extensions import ParamSpec
2422
from idom import use_callback
2523

@@ -68,6 +66,7 @@ def use_websocket() -> IdomWebsocket:
6866
def use_query(
6967
query: Callable[_Params, _Data],
7068
*args: _Params.args,
69+
fetch_deferred_fields: bool = True,
7170
**kwargs: _Params.kwargs,
7271
) -> Query[_Data]:
7372
given_query = query
@@ -99,15 +98,33 @@ def execute_query():
9998

10099
def thread_target():
101100
try:
102-
returned = query(*args, **kwargs)
101+
query_result = query(*args, **kwargs)
103102
except Exception as e:
104103
set_data(UNDEFINED)
105104
set_loading(False)
106105
set_error(e)
107-
else:
108-
set_data(returned)
109-
set_loading(False)
110-
set_error(None)
106+
return
107+
108+
if isinstance(query_result, QuerySet):
109+
if fetch_deferred_fields:
110+
for model in query_result:
111+
_fetch_deferred_fields(model)
112+
else:
113+
# still force query set to execute
114+
for _ in query_result:
115+
pass
116+
elif isinstance(query_result, Model):
117+
if fetch_deferred_fields:
118+
_fetch_deferred_fields(query_result)
119+
elif fetch_deferred_fields:
120+
raise ValueError(
121+
f"Expected {query} to return Model or Query because "
122+
f"{fetch_deferred_fields=}, got {query_result!r}"
123+
)
124+
125+
set_data(query_result)
126+
set_loading(False)
127+
set_error(None)
111128

112129
# We need to run this in a thread so we don't prevent rendering when loading.
113130
# I'm also hoping that Django is ok with this since this thread won't have an
@@ -167,3 +184,13 @@ class Mutation(NamedTuple, Generic[_Params]):
167184
loading: bool
168185
error: Exception | None
169186
reset: Callable[[], None]
187+
188+
189+
_Model = TypeVar("_Model", bound=Model)
190+
191+
192+
def _fetch_deferred_fields(model: _Model) -> _Model:
193+
for field in model._meta.get_fields():
194+
value = getattr(model, field.name)
195+
if isinstance(value, Model):
196+
_fetch_deferred_fields(value)

0 commit comments

Comments
 (0)