29
29
from reactpy_django .types import (
30
30
AsyncMessageReceiver ,
31
31
AsyncMessageSender ,
32
+ AsyncPostprocessor ,
32
33
ConnectionType ,
33
34
FuncParams ,
34
35
Inferred ,
35
36
Mutation ,
36
37
MutationOptions ,
37
38
Query ,
38
39
QueryOptions ,
40
+ SyncPostprocessor ,
39
41
UserData ,
40
42
)
41
43
from reactpy_django .utils import generate_obj_name , get_pk
@@ -102,48 +104,39 @@ def use_connection() -> ConnectionType:
102
104
return _use_connection ()
103
105
104
106
105
- @overload
106
- def use_query (
107
- options : QueryOptions ,
108
- / ,
109
- query : Callable [FuncParams , Awaitable [Inferred ]] | Callable [FuncParams , Inferred ],
110
- * args : FuncParams .args ,
111
- ** kwargs : FuncParams .kwargs ,
112
- ) -> Query [Inferred ]: ...
113
-
114
-
115
- @overload
116
107
def use_query (
117
108
query : Callable [FuncParams , Awaitable [Inferred ]] | Callable [FuncParams , Inferred ],
109
+ / ,
118
110
* args : FuncParams .args ,
111
+ thread_sensitive : bool = True ,
112
+ postprocessor : AsyncPostprocessor | SyncPostprocessor | None = None ,
113
+ postprocessor_kwargs : dict [str , Any ] | None = None ,
119
114
** kwargs : FuncParams .kwargs ,
120
- ) -> Query [Inferred ]: ...
121
-
122
-
123
- def use_query (* args , ** kwargs ) -> Query [Inferred ]:
115
+ ) -> Query [Inferred ]:
124
116
"""This hook is used to execute functions in the background and return the result, \
125
117
typically to read data the Django ORM.
126
118
127
119
Args:
128
- options: An optional `QueryOptions` object that can modify how the query is executed.
129
120
query: A callable that returns a Django `Model` or `QuerySet`.
130
- *args: Positional arguments to pass into `query`.
131
-
132
- Keyword Args:
133
- **kwargs: Keyword arguments to pass into `query`."""
121
+ args: Positional arguments to passed into the `query` function.
122
+ kwargs: Keyword arguments to passed into the `query` function.
123
+ thread_sensitive: Whether to run the query in thread-sensitive mode. \
124
+ This setting only applies to sync query functions.
125
+ postprocessor: A callable that processes the query result prior to returning it. \
126
+ The first argument of postprocessor function must be the query `data`. All \
127
+ proceeding arguments are optional `postprocessor_kwargs` (see below). This \
128
+ postprocessor function must return the modified `data`. \
129
+ \
130
+ If unset, `REACTPY_DEFAULT_QUERY_POSTPROCESSOR` is used. By default, this \
131
+ is used to prevent Django's lazy query execution and supports `many_to_many` \
132
+ and `many_to_one` as `postprocessor_kwargs`.
133
+ postprocessor_kwargs: Keyworded arguments passed into the `postprocessor` function.
134
+ """
134
135
135
136
should_execute , set_should_execute = use_state (True )
136
137
data , set_data = use_state (cast (Inferred , None ))
137
138
loading , set_loading = use_state (True )
138
139
error , set_error = use_state (cast (Union [Exception , None ], None ))
139
- if isinstance (args [0 ], QueryOptions ):
140
- query_options , query , query_args , query_kwargs = _use_query_args_1 (
141
- * args , ** kwargs
142
- )
143
- else :
144
- query_options , query , query_args , query_kwargs = _use_query_args_2 (
145
- * args , ** kwargs
146
- )
147
140
query_ref = use_ref (query )
148
141
if query_ref .current is not query :
149
142
raise ValueError (f"Query function changed from { query_ref .current } to { query } ." )
@@ -153,24 +146,21 @@ async def execute_query() -> None:
153
146
try :
154
147
# Run the query
155
148
if asyncio .iscoroutinefunction (query ):
156
- new_data = await query (* query_args , ** query_kwargs )
149
+ new_data = await query (* args , ** kwargs )
157
150
else :
158
151
new_data = await database_sync_to_async (
159
152
query ,
160
- thread_sensitive = query_options . thread_sensitive ,
161
- )(* query_args , ** query_kwargs )
153
+ thread_sensitive = thread_sensitive ,
154
+ )(* args , ** kwargs )
162
155
163
156
# Run the postprocessor
164
- if query_options .postprocessor :
165
- if asyncio .iscoroutinefunction (query_options .postprocessor ):
166
- new_data = await query_options .postprocessor (
167
- new_data , ** query_options .postprocessor_kwargs
168
- )
157
+ if postprocessor :
158
+ if asyncio .iscoroutinefunction (postprocessor ):
159
+ new_data = await postprocessor (new_data , ** postprocessor_kwargs )
169
160
else :
170
161
new_data = await database_sync_to_async (
171
- query_options .postprocessor ,
172
- thread_sensitive = query_options .thread_sensitive ,
173
- )(new_data , ** query_options .postprocessor_kwargs )
162
+ postprocessor , thread_sensitive = thread_sensitive
163
+ )(new_data , ** postprocessor_kwargs )
174
164
175
165
# Log any errors and set the error state
176
166
except Exception as e :
@@ -216,26 +206,14 @@ def register_refetch_callback() -> Callable[[], None]:
216
206
return Query (data , loading , error , refetch )
217
207
218
208
219
- @overload
220
- def use_mutation (
221
- options : MutationOptions ,
222
- mutation : (
223
- Callable [FuncParams , bool | None ] | Callable [FuncParams , Awaitable [bool | None ]]
224
- ),
225
- refetch : Callable [..., Any ] | Sequence [Callable [..., Any ]] | None = None ,
226
- ) -> Mutation [FuncParams ]: ...
227
-
228
-
229
- @overload
230
209
def use_mutation (
231
210
mutation : (
232
211
Callable [FuncParams , bool | None ] | Callable [FuncParams , Awaitable [bool | None ]]
233
212
),
213
+ / ,
214
+ thread_sensitive : bool = True ,
234
215
refetch : Callable [..., Any ] | Sequence [Callable [..., Any ]] | None = None ,
235
- ) -> Mutation [FuncParams ]: ...
236
-
237
-
238
- def use_mutation (* args : Any , ** kwargs : Any ) -> Mutation [FuncParams ]:
216
+ ) -> Mutation [FuncParams ]:
239
217
"""This hook is used to modify data in the background, typically to create/update/delete \
240
218
data from the Django ORM.
241
219
@@ -246,6 +224,8 @@ def use_mutation(*args: Any, **kwargs: Any) -> Mutation[FuncParams]:
246
224
mutation: A callable that performs Django ORM create, update, or delete \
247
225
functionality. If this function returns `False`, then your `refetch` \
248
226
function will not be used.
227
+ thread_sensitive: Whether to run the mutation in thread-sensitive mode. \
228
+ This setting only applies to sync mutation functions.
249
229
refetch: A query function (the function you provide to your `use_query` \
250
230
hook) or a sequence of query functions that need a `refetch` if the \
251
231
mutation succeeds. This is useful for refreshing data after a mutation \
@@ -254,10 +234,6 @@ def use_mutation(*args: Any, **kwargs: Any) -> Mutation[FuncParams]:
254
234
255
235
loading , set_loading = use_state (False )
256
236
error , set_error = use_state (cast (Union [Exception , None ], None ))
257
- if isinstance (args [0 ], MutationOptions ):
258
- mutation_options , mutation , refetch = _use_mutation_args_1 (* args , ** kwargs )
259
- else :
260
- mutation_options , mutation , refetch = _use_mutation_args_2 (* args , ** kwargs )
261
237
262
238
# The main "running" function for `use_mutation`
263
239
async def execute_mutation (exec_args , exec_kwargs ) -> None :
@@ -267,7 +243,7 @@ async def execute_mutation(exec_args, exec_kwargs) -> None:
267
243
should_refetch = await mutation (* exec_args , ** exec_kwargs )
268
244
else :
269
245
should_refetch = await database_sync_to_async (
270
- mutation , thread_sensitive = mutation_options . thread_sensitive
246
+ mutation , thread_sensitive = thread_sensitive
271
247
)(* exec_args , ** exec_kwargs )
272
248
273
249
# Log any errors and set the error state
@@ -444,22 +420,6 @@ def use_root_id() -> str:
444
420
return scope ["reactpy" ]["id" ]
445
421
446
422
447
- def _use_query_args_1 (options : QueryOptions , / , query : Query , * args , ** kwargs ):
448
- return options , query , args , kwargs
449
-
450
-
451
- def _use_query_args_2 (query : Query , * args , ** kwargs ):
452
- return QueryOptions (), query , args , kwargs
453
-
454
-
455
- def _use_mutation_args_1 (options : MutationOptions , mutation : Mutation , refetch = None ):
456
- return options , mutation , refetch
457
-
458
-
459
- def _use_mutation_args_2 (mutation , refetch = None ):
460
- return MutationOptions (), mutation , refetch
461
-
462
-
463
423
async def _get_user_data (
464
424
user : AbstractUser , default_data : None | dict , save_default_data : bool
465
425
) -> dict | None :
0 commit comments