You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/includes/orm.md
+2-2
Original file line number
Diff line number
Diff line change
@@ -2,12 +2,12 @@
2
2
3
3
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a `#!python SynchronousOnlyOperation` exception.
4
4
5
-
These `#!python SynchronousOnlyOperation` exceptions may be resolved in a future version of Django containing an asynchronous ORM. However, it is best practice to always perform ORM calls in the background via hooks.
5
+
These `#!python SynchronousOnlyOperation` exceptions may be removed in a future version of Django. However, it is best practice to always perform IO operations (such as ORM queries) via hooks to prevent performance issues.
6
6
7
7
<!--orm-excp-end-->
8
8
9
9
<!--orm-fetch-start-->
10
10
11
-
By default, automatic recursive fetching of `#!python ManyToMany` or `#!python ForeignKey` fields is enabled within the default `#!python QueryOptions.postprocessor`. This is needed to prevent `#!python SynchronousOnlyOperation` exceptions when accessing these fields within your ReactPy components.
11
+
By default, automatic recursive fetching of `#!python ManyToMany` or `#!python ForeignKey` fields is enabled within the `DjangoQueryPostprocessor`. This is needed to prevent `#!python SynchronousOnlyOperation` exceptions when accessing these fields within your ReactPy components.
Copy file name to clipboardExpand all lines: docs/src/reference/components.md
+12-16
Original file line number
Diff line number
Diff line change
@@ -177,7 +177,7 @@ Allows you to defer loading a CSS stylesheet until a component begins rendering.
177
177
178
178
| Name | Type | Description | Default |
179
179
| --- | --- | --- | --- |
180
-
| `#!python static_path` | `#!python str` | The path to the static file. This path is identical to what you would use on a `static` template tag. | N/A |
180
+
| `#!python static_path` | `#!python str` | The path to the static file. This path is identical to what you would use on Django's `#!jinja {% static %}` template tag. | N/A |
181
181
| `#!python key` | `#!python Key | None` | A key to uniquely identify this component which is unique amongst a component's immediate siblings | `#!python None` |
182
182
183
183
<font size="4">**Returns**</font>
@@ -186,10 +186,6 @@ Allows you to defer loading a CSS stylesheet until a component begins rendering.
186
186
| --- | --- |
187
187
| `#!python Component` | A ReactPy component. |
188
188
189
-
??? question "Should I put `#!python django_css` at the top of my HTML?"
190
-
191
-
Yes, if the stylesheet contains styling for your component.
192
-
193
189
??? question "Can I load static CSS using `#!python html.link` instead?"
194
190
195
191
While you can load stylesheets with `#!python html.link`, keep in mind that loading this way **does not** ensure load order. Thus, your stylesheet will be loaded after your component is displayed. This would likely cause unintended visual behavior, so use this at your own discretion.
@@ -204,22 +200,26 @@ Allows you to defer loading a CSS stylesheet until a component begins rendering.
204
200
205
201
`#!python django_css` can only be used with local static files.
206
202
207
-
For external CSS, substitute `#!python django_css` with `#!python html.link`.
203
+
For external CSS, you should use `#!python html.link`.
208
204
209
205
```python
210
206
{% include "../../python/django-css-external-link.py" %}
211
207
```
212
208
213
209
??? question "Why not load my CSS in `#!html <head>`?"
214
210
215
-
Traditionally, stylesheets are loaded in your `#!html <head>` using the `#!jinja {% load static %}` template tag.
211
+
Traditionally, stylesheets are loaded in your `#!html <head>` using Django's `#!jinja {% static %}` template tag.
216
212
217
-
To help improve webpage load times, you can use the `#!python django_css` component to defer loading your stylesheet until it is needed.
213
+
However, to help improve webpage load times you can use this `#!python django_css` component to defer loading your stylesheet until it is needed.
218
214
219
215
## Django JS
220
216
221
217
Allows you to defer loading JavaScript until a component begins rendering. This JavaScript must be stored within [Django's static files](https://docs.djangoproject.com/en/dev/howto/static-files/).
222
218
219
+
!!! warning "Pitfall"
220
+
221
+
Be mindful of load order! If your JavaScript relies on the component existing on the page, you must place `django_js` at the **bottom** of your component.
222
+
223
223
=== "components.py"
224
224
225
225
```python
@@ -232,7 +232,7 @@ Allows you to defer loading JavaScript until a component begins rendering. This
232
232
233
233
| Name | Type | Description | Default |
234
234
| --- | --- | --- | --- |
235
-
| `#!python static_path` | `#!python str` | The path to the static file. This path is identical to what you would use on a `static` template tag. | N/A |
235
+
| `#!python static_path` | `#!python str` | The path to the static file. This path is identical to what you would use on Django's `#!jinja {% static %}` template tag. | N/A |
236
236
| `#!python key` | `#!python Key | None` | A key to uniquely identify this component which is unique amongst a component's immediate siblings | `#!python None` |
237
237
238
238
<font size="4">**Returns**</font>
@@ -241,10 +241,6 @@ Allows you to defer loading JavaScript until a component begins rendering. This
241
241
| --- | --- |
242
242
| `#!python Component` | A ReactPy component. |
243
243
244
-
??? question "Should I put `#!python django_js` at the bottom of my HTML?"
245
-
246
-
Yes, if your scripts are reliant on the contents of the component.
247
-
248
244
??? question "Can I load static JavaScript using `#!python html.script` instead?"
249
245
250
246
While you can load JavaScript with `#!python html.script`, keep in mind that loading this way **does not** ensure load order. Thus, your JavaScript will likely be loaded at an arbitrary time after your component is displayed.
@@ -259,14 +255,14 @@ Allows you to defer loading JavaScript until a component begins rendering. This
259
255
260
256
`#!python django_js` can only be used with local static files.
261
257
262
-
For external JavaScript, substitute `#!python django_js` with `#!python html.script`.
258
+
For external JavaScript, you should use `#!python html.script`.
263
259
264
260
```python
265
261
{% include "../../python/django-js-remote-script.py" %}
266
262
```
267
263
268
264
??? question "Why not load my JS in `#!html <head>`?"
269
265
270
-
Traditionally, JavaScript is loaded in your `#!html <head>` using the `#!jinja {% load static %}` template tag.
266
+
Traditionally, JavaScript is loaded in your `#!html <head>` using Django's `#!jinja {% static %}` template tag.
271
267
272
-
To help improve webpage load times, you can use the `#!python django_js` component to defer loading your JavaScript until it is needed.
268
+
However, to help improve webpage load times you can use this `#!python django_js` component to defer loading your JavaScript until it is needed.
Copy file name to clipboardExpand all lines: docs/src/reference/hooks.md
+64-32
Original file line number
Diff line number
Diff line change
@@ -16,9 +16,9 @@ Prefabricated hooks can be used within your `components.py` to help simplify dev
16
16
17
17
## Use Query
18
18
19
-
This hook is used [read](https://www.sumologic.com/glossary/crud/) data from the Django ORM.
19
+
This hook is used [read](https://www.sumologic.com/glossary/crud/) data, typically from the Django ORM.
20
20
21
-
The query function you provide must return either a `#!python Model` or `#!python QuerySet`.
21
+
The [default postprocessor](../reference/utils.md#django-query-postprocessor) expects your query function to return either a Django `#!python Model` or `#!python QuerySet`. The postprocessor needs to be changed to perform other types of queries. Query functions can be sync or async.
22
22
23
23
=== "components.py"
24
24
@@ -59,13 +59,13 @@ The query function you provide must return either a `#!python Model` or `#!pytho
59
59
{% include "../../python/use-query-args.py" %}
60
60
```
61
61
62
-
??? question "Why does `#!python get_items` in the example return `#!python TodoItem.objects.all()`?"
62
+
??? question "How can I customize this hook's behavior?"
63
63
64
-
This was a technical design decision to based on [Apollo's `#!javascript useQuery` hook](https://www.apollographql.com/docs/react/data/queries/), but ultimately helps avoid Django's `#!python SynchronousOnlyOperation` exceptions.
64
+
This hook accepts a `#!python options = ...` parameter that can be used to customize its behavior. You can provide a `#!python reactpy_django.types.QueryOptions` object to this parameter to customize the hook's behavior.
65
65
66
-
The `#!python use_query` hook ensures the provided `#!python Model` or `#!python QuerySet` executes all [deferred](https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_deferred_fields)/[lazy queries](https://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy) safely prior to reaching your components.
66
+
Below are the settings that can be modified via `#!python QueryOptions`.
67
67
68
-
??? question "How can I use `#!python QueryOptions` to customize fetching behavior?"
@@ -128,27 +128,39 @@ The query function you provide must return either a `#!python Model` or `#!pytho
128
128
129
129
_Note: In Django's ORM design, the field name to access foreign keys is [postfixed with `_set`](https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_one/) by default._
130
130
131
-
??? question "Can I define async query functions?"
131
+
??? question "Can I make ORM calls without hooks?"
??? question "Why does the example query function return `#!python TodoItem.objects.all()`?"
154
+
155
+
This design decision was based on [Apollo's `#!javascript useQuery` hook](https://www.apollographql.com/docs/react/data/queries/), but ultimately helps avoid Django's `#!python SynchronousOnlyOperation` exceptions.
156
+
157
+
With the `#!python Model` or `#!python QuerySet` your function returns, this hook uses the [default postprocessor](../reference/utils.md#django-query-postprocessor) to ensure that all [deferred](https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_deferred_fields) or [lazy](https://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy) fields are executed.
146
158
147
159
## Use Mutation
148
160
149
-
This hook is used to [create, update, or delete](https://www.sumologic.com/glossary/crud/) Django ORM objects.
161
+
This hook is used to [create, update, or delete](https://www.sumologic.com/glossary/crud/)data, typically from the Django ORM.
150
162
151
-
The mutation function you provide should have no return value.
163
+
The mutation function you provide should have no return value. Mutation functions can be sync or async.
152
164
153
165
=== "components.py"
154
166
@@ -187,27 +199,31 @@ The mutation function you provide should have no return value.
187
199
{% include "../../python/use-mutation-args-kwargs.py" %}
188
200
```
189
201
190
-
??? question "Can `#!python use_mutation` trigger a refetch of `#!python use_query`?"
202
+
??? question "How can I customize this hook's behavior?"
191
203
192
-
Yes, `#!python use_mutation` can queue a refetch of a `#!python use_query` via the `#!python refetch=...` argument.
204
+
This hook accepts a `#!python options = ...` parameter that can be used to customize its behavior. You can provide a `#!python reactpy_django.types.MutationOptions` object to this parameter to customize the hook's behavior.
193
205
194
-
The example below is a merge of the `#!python use_query` and `#!python use_mutation` examples above with the addition of a `#!python use_mutation(refetch=...)` argument.
206
+
Below are the settings that can be modified via `#!python MutationOptions`.
195
207
196
-
Please note that any `#!python use_query` hooks that use `#!python get_items` will be refetched upon a successful mutation.
Whether to run your synchronous mutation function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's [`#!python sync_to_async` docs](https://docs.djangoproject.com/en/dev/topics/async/#sync-to-async) docs for more information.
213
+
214
+
This setting only applies to sync query functions, and will be ignored for async functions.
197
215
198
216
=== "components.py"
199
217
200
218
```python
201
-
{% include "../../python/use-mutation-query-refetch.py" %}
219
+
{% include "../../python/use-mutation-thread-sensitive.py" %}
202
220
```
203
221
204
-
=== "models.py"
222
+
??? question "Can I make ORM calls without hooks?"
Yes, `#!python use_mutation` can queue a refetch of a `#!python use_query` via the `#!python refetch=...` argument.
247
+
248
+
The example below is a merge of the `#!python use_query` and `#!python use_mutation` examples above with the addition of a `#!python use_mutation(refetch=...)` argument.
249
+
250
+
Please note that `refetch` will cause all `#!python use_query` hooks that use `#!python get_items` in the current component tree will be refetched.
251
+
252
+
=== "components.py"
253
+
254
+
```python
255
+
{% include "../../python/use-mutation-query-refetch.py" %}
256
+
```
257
+
258
+
=== "models.py"
259
+
260
+
```python
261
+
{% include "../../python/example/models.py" %}
262
+
```
231
263
232
264
## Use Connection
233
265
234
-
This hook is used to fetch the Django Channels [WebSocket](https://channels.readthedocs.io/en/stable/topics/consumers.html#asyncjsonwebsocketconsumer).
266
+
This hook is used to fetch the active connection, which is either a Django [WebSocket](https://channels.readthedocs.io/en/stable/topics/consumers.html#asyncjsonwebsocketconsumer) or a [HTTP Request](https://docs.djangoproject.com/en/4.2/ref/request-response/#django.http.HttpRequest).
235
267
236
268
=== "components.py"
237
269
@@ -249,11 +281,11 @@ This hook is used to fetch the Django Channels [WebSocket](https://channels.read
249
281
250
282
| Type | Description |
251
283
| --- | --- |
252
-
| `#!python Connection` | The component's WebSocket. |
284
+
| `#!python Connection` | The component's `WebSocket` or `HttpRequest`. |
253
285
254
286
## Use Scope
255
287
256
-
This is a shortcut that returns the WebSocket's[`#!python scope`](https://channels.readthedocs.io/en/stable/topics/consumers.html#scope).
288
+
This is a shortcut that returns the HTTP or WebSocket [`#!python scope`](https://channels.readthedocs.io/en/stable/topics/consumers.html#scope).
257
289
258
290
=== "components.py"
259
291
@@ -275,7 +307,7 @@ This is a shortcut that returns the WebSocket's [`#!python scope`](https://chann
275
307
276
308
## Use Location
277
309
278
-
This is a shortcut that returns the WebSocket's `#!python path`.
310
+
This is a shortcut that returns the client's `#!python path`.
279
311
280
312
You can expect this hook to provide strings such as `/reactpy/my_path`.
281
313
@@ -299,7 +331,7 @@ You can expect this hook to provide strings such as `/reactpy/my_path`.
299
331
300
332
??? info "This hook's behavior will be changed in a future update"
301
333
302
-
This hook will be updated to return the browser's currently active HTTP path. This change will come in alongside ReactPy URL routing support.
334
+
This hook will be updated to always return the browser's currently active HTTP path. This change will come in alongside ReactPy URL routing support.
303
335
304
336
Check out [reactive-python/reactpy-django#147](https://github.com/reactive-python/reactpy-django/issues/147) for more information.
305
337
@@ -325,4 +357,4 @@ You can expect this hook to provide strings such as `http://example.com`.
325
357
326
358
| Type | Description |
327
359
| --- | --- |
328
-
| `#!python str | None` | A string containing the browser's current origin, obtained from WebSocket headers (if available). |
360
+
| `#!python str | None` | A string containing the browser's current origin, obtained from WebSocket or HTTP headers (if available). |
Copy file name to clipboardExpand all lines: docs/src/reference/template-tag.md
+1-1
Original file line number
Diff line number
Diff line change
@@ -81,7 +81,7 @@ This template tag can be used to insert any number of ReactPy components onto yo
81
81
Here's a couple of things to keep in mind:
82
82
83
83
1. If your host address are completely separate ( `origin1.com != origin2.com` ) you will need to [configure CORS headers](https://pypi.org/project/django-cors-headers/) on your main application during deployment.
84
-
2. You will not need to register ReactPy HTTP or WebSocket paths on any applications that do not perform any component rendering.
84
+
2. You will not need to register ReactPy WebSocket or HTTP paths on any applications that do not perform any component rendering.
85
85
3. Your component will only be able to access your template tag's `#!python *args`/`#!python **kwargs` if your applications share a common database.
0 commit comments