Prettier WebSocket URLs for components that do not have sessions.
Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
Bumped the minimum @reactpy/client version to 0.3.1
Bumped the minimum Django version to 4.2.
Use TypeScript instead of JavaScript for this repository.
Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This "latest-only" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.
Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.
ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.
django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.
django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.
Prettier WebSocket URLs for components that do not have sessions.
Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
Bumped the minimum @reactpy/client version to 0.3.1
Bumped the minimum Django version to 4.2.
Use TypeScript instead of JavaScript for this repository.
Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This "latest-only" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.
Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.
ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.
django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.
django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.
You will need to set up a Python environment to develop ReactPy-Django.
Note
Looking to contribute features that are not Django specific?
Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.
You will need to set up a Python environment to develop ReactPy-Django.
Note
Looking to contribute features that are not Django specific?
Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.
\ No newline at end of file
diff --git a/develop/about/license/index.html b/develop/about/license/index.html
new file mode 100644
index 00000000..ee9a1782
--- /dev/null
+++ b/develop/about/license/index.html
@@ -0,0 +1 @@
+ License - ReactPy-Django
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.
Note
These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.
If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.
Note
These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.
\ No newline at end of file
diff --git a/develop/learn/your-first-component/index.html b/develop/learn/your-first-component/index.html
index 194d50d3..8fe3103b 100644
--- a/develop/learn/your-first-component/index.html
+++ b/develop/learn/your-first-component/index.html
@@ -1,4 +1,4 @@
- Your First Component - ReactPy-Django
Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!
Note
If you have reached this point, you should have already installed ReactPy-Django through the previous steps.
You will need a file to start creating ReactPy components.
We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.
Within this file, you can define your component functions using ReactPy's @component decorator.
Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!
Note
If you have reached this point, you should have already installed ReactPy-Django through the previous steps.
You will need a file to start creating ReactPy components.
We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.
Within this file, you can define your component functions using ReactPy's @component decorator.
Do not use context variables for the component path
The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
For example, do not do the following:
1
+
Do not use context variables for the component path
The ReactPy component finder requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
For simple Django projects, you can easily add all of your views directly into the Django project'surls.py. However, as you start increase your project's complexity you might end up with way too much within one file.
Once you reach that point, we recommend creating an individual urls.py within each of your Django apps.
Then, within your Django project'surls.py you will use Django's include function to link it all together.
Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.
Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.
The path to the static file. This path is identical to what you would use on a static template tag.
N/A
key
Key|None
A key to uniquely identify this component which is unique amongst a component's immediate siblings
None
Returns
Type
Description
Component
A ReactPy component.
Should I put django_css at the top of my HTML?
Yes, if the stylesheet contains styling for your component.
Can I load static CSS using html.link instead?
While you can load stylesheets with 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.
Here's an example on what you should avoid doing for Django static files:
1
+
See Interface
Parameters
Name
Type
Description
Default
static_path
str
The path to the static file. This path is identical to what you would use on Django's {%static%} template tag.
N/A
key
Key|None
A key to uniquely identify this component which is unique amongst a component's immediate siblings
None
Returns
Type
Description
Component
A ReactPy component.
Can I load static CSS using html.link instead?
While you can load stylesheets with 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.
Here's an example on what you should avoid doing for Django static files:
The path to the static file. This path is identical to what you would use on a static template tag.
N/A
key
Key|None
A key to uniquely identify this component which is unique amongst a component's immediate siblings
None
Returns
Type
Description
Component
A ReactPy component.
Should I put django_js at the bottom of my HTML?
Yes, if your scripts are reliant on the contents of the component.
Can I load static JavaScript using html.script instead?
While you can load JavaScript with 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.
Here's an example on what you should avoid doing for Django static files:
1
+
See Interface
Parameters
Name
Type
Description
Default
static_path
str
The path to the static file. This path is identical to what you would use on Django's {%static%} template tag.
N/A
key
Key|None
A key to uniquely identify this component which is unique amongst a component's immediate siblings
None
Returns
Type
Description
Component
A ReactPy component.
Can I load static JavaScript using html.script instead?
While you can load JavaScript with 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.
Here's an example on what you should avoid doing for Django static files:
This hook is used to execute functions in the background and return the result, typically to read data the Django ORM.
The default postprocessor expects your query function to return a Django Model or QuerySet. The postprocessor needs to be changed to execute other types of queries. Query functions can be sync or async.
Why does get_items in the example return TodoItem.objects.all()?
This was a technical design decision to based on Apollo's useQuery hook, but ultimately helps avoid Django's SynchronousOnlyOperation exceptions.
The use_query hook ensures the provided Model or QuerySet executes all deferred/lazy queries safely prior to reaching your components.
How can I use QueryOptions to customize fetching behavior?
thread_sensitive
Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
1
+
How can I customize this hook's behavior?
This hook accepts a options:QueryOptions parameter that can be used to customize behavior.
Below are the settings that can be modified via these QueryOptions.
thread_sensitive
Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you...
Want to use this hook to defer IO intensive tasks to be computed in the background
Want to to utilize use_query with a different ORM
... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.
1
+
postprocessor
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you...
Want to use this hook to defer IO intensive tasks to be computed in the background
Want to to utilize use_query with a different ORM
... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.
You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.
1
+
postprocessor_kwargs
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.
You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.
1 2 3 4
@@ -285,7 +287,7 @@
# By disabling `many_to_many` and `many_to_one`, accessing these fields will now# generate a `SynchronousOnlyOperation` exceptionreturnf"{query.data.many_to_many_field}{query.data.foriegn_key_field_set}"
-
Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.
Can I define async query functions?
Async functions are supported by use_query. You can use them in the same way as a sync query function.
However, be mindful of Django async ORM restrictions.
1
+
Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
Can I make a failed query try again?
Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used.
A query function (used by the use_query hook) or a sequence of query functions that will be called if the mutation succeeds. This is useful for refetching data after a mutation has been performed.
None
Returns
Type
Description
Mutation[_Params]
An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query.
How can I provide arguments to my mutation function?
*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.
1
+
See Interface
Parameters
Name
Type
Description
Default
mutate
Callable[_Params,bool|None]
A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used.
A query function (the function you provide to your use_query hook) or a sequence of query functions that need a refetch if the mutation succeeds. This is useful for refreshing data after a mutation has been performed.
None
Returns
Type
Description
Mutation[_Params]
An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query.
How can I provide arguments to my mutation function?
*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.
Yes, use_mutation can queue a refetch of a use_query via the refetch=... argument.
The example below is a merge of the use_query and use_mutation examples above with the addition of a use_mutation(refetch=...) argument.
Please note that any use_query hooks that use get_items will be refetched upon a successful mutation.
1
+
How can I customize this hook's behavior?
This hook accepts a options:MutationOptions parameter that can be used to customize behavior.
Below are the settings that can be modified via these MutationOptions.
thread_sensitive
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 sync_to_async docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
fromreactpyimportcomponent,html
+fromreactpy_django.hooksimportuse_mutation
+fromreactpy_django.typesimportMutationOptions
-defget_items():
- returnTodoItem.objects.all()
+defexecute_thread_safe_mutation():
+"""This is an example mutation function that does some thread-safe operation."""
+ pass
+
+
+@component
+defmy_component():
+ item_mutation=use_mutation(
+ MutationOptions(thread_sensitive=False),
+ execute_thread_safe_mutation,
+ )
+
+ defsubmit_event(event):
+ ifevent["key"]=="Enter":
+ item_mutation.execute(text=event["target"]["value"])
+
+ ifitem_mutation.loadingoritem_mutation.error:
+ mutation_status=html.h2("Doing something...")
+ elifitem_mutation.error:
+ mutation_status=html.h2("Error!")
+ else:
+ mutation_status=html.h2("Done.")
+
+ returnhtml.div(
+ html.input({"type":"text","onKeyDown":submit_event}),
+ mutation_status,
+ )
+
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
Can I make a failed mutation try again?
Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
Configures whether ReactPy components are rendered in a dedicated thread.
This setting allows the web server to process other traffic during ReactPy rendering. Vastly improves throughput with web servers such as hypercorn and uvicorn.
Configures whether ReactPy components are rendered in a dedicated thread.
This setting allows the web server to process other traffic during ReactPy rendering. Vastly improves throughput with web servers such as hypercorn and uvicorn.
\ No newline at end of file
diff --git a/develop/reference/template-tag/index.html b/develop/reference/template-tag/index.html
index 2ae3416f..f3c74dd2 100644
--- a/develop/reference/template-tag/index.html
+++ b/develop/reference/template-tag/index.html
@@ -1,4 +1,4 @@
- Template Tag - ReactPy-Django
The positional arguments to provide to the component.
N/A
class
str|None
The HTML class to apply to the top-level component div.
None
key
Any
Force the component's root node to use a specific key value. Using key within a template tag is effectively useless.
None
host
str|None
The host to use for the ReactPy connections. If unset, the host will be automatically configured. Example values include: localhost:8000, example.com, example.com/subdir
None
prerender
str
If "True", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency.
"False"
**kwargs
Any
The keyword arguments to provide to the component.
N/A
Returns
Type
Description
Component
A ReactPy component.
Do not use context variables for the component path
The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
For example, do not do the following:
1
+
See Interface
Parameters
Name
Type
Description
Default
dotted_path
str
The dotted path to the component to render.
N/A
*args
Any
The positional arguments to provide to the component.
N/A
class
str|None
The HTML class to apply to the top-level component div.
None
key
Any
Force the component's root node to use a specific key value. Using key within a template tag is effectively useless.
None
host
str|None
The host to use for the ReactPy connections. If unset, the host will be automatically configured. Example values include: localhost:8000, example.com, example.com/subdir
None
prerender
str
If "True", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency.
"False"
**kwargs
Any
The keyword arguments to provide to the component.
N/A
Returns
Type
Description
Component
A ReactPy component.
Do not use context variables for the component path
The ReactPy component finder requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.
Here's a couple of things to keep in mind:
If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
You will not need to register ReactPy HTTP or WebSocket paths on any applications that do not perform any component rendering.
Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?
You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.
1
+
This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.
Here's a couple of things to keep in mind:
If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
You will not need to register ReactPy WebSocket or HTTP paths on any applications that do not perform any component rendering.
Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?
You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.
This is the default postprocessor for the use_query hook.
This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.
This is the default postprocessor for the use_query hook.
This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.
1 2 3 4
@@ -67,4 +67,4 @@
defready(self):# Add components to the ReactPy component registry when Django is readyregister_component("example_project.my_app.components.hello_world")
-
Only use this within MyAppConfig.ready()
You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.
Do I need to use this?
You typically will not need to use this function.
For security reasons, ReactPy does not allow non-registered components to be root components. However, all components contained within Django templates are automatically considered root components.
This is typically only needed when you have a dedicated Django application as a rendering server that doesn't have templates, such as when modifying the template tag host argument. On this dedicated rendering server, you would need to manually register your components.
You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.
Do I need to use this?
You typically will not need to use this function.
For security reasons, ReactPy requires all root components to be registered. However, all components contained within Django templates are automatically registered.
This function is needed when you have configured your host to a dedicated Django rendering application that doesn't have templates.
\ No newline at end of file
diff --git a/develop/search/search_index.json b/develop/search/search_index.json
index e1579b2a..ee95f7be 100644
--- a/develop/search/search_index.json
+++ b/develop/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"about/changelog/","title":"Changelog","text":"
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Prettier WebSocket URLs for components that do not have sessions.
Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
Bumped the minimum @reactpy/client version to 0.3.1
Bumped the minimum Django version to 4.2.
Use TypeScript instead of JavaScript for this repository.
Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This \"latest-only\" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.
Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.
ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.
django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.
django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.
You will need to set up a Python environment to develop ReactPy-Django.
Note
Looking to contribute features that are not Django specific?
Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.
"},{"location":"about/code/#creating-an-environment","title":"Creating an environment","text":"
If you plan to make code changes to this repository, you will need to install the following dependencies first:
Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.
To learn how to create GitHub PRs, click here.
"},{"location":"learn/add-reactpy-to-a-django-project/","title":"Add ReactPy to a Django Project","text":""},{"location":"learn/add-reactpy-to-a-django-project/#overview","title":"Overview","text":"
If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.
Note
These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.
If do not have a Django project, check out this 9 minute YouTube tutorial created by IDG TECHtalk.
"},{"location":"learn/add-reactpy-to-a-django-project/#step-1-install-from-pypi","title":"Step 1: Install from PyPI","text":"
Run the following command to install reactpy-django in your Python environment.
If you do not have an asgi.py, follow the channels installation guide.
"},{"location":"learn/add-reactpy-to-a-django-project/#step-5-run-database-migrations","title":"Step 5: Run database migrations","text":"
Run Django's migrate command to initialize ReactPy-Django's database table.
python manage.py migrate\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-6-check-your-configuration","title":"Step 6: Check your configuration","text":"
Run Django's check command to verify if ReactPy was set up correctly.
python manage.py check\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-7-create-your-first-component","title":"Step 7: Create your first component","text":"
The next step will show you how to create your first ReactPy component.
Prefer a quick summary? Read the At a Glance section below.
At a Glance: Your First Component
my_app/components.py
You will need a file to define your ReactPy components. We recommend creating a components.py file within your chosen Django app to start out. Within this file, we will create a simple hello_world component.
from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n return html.h1(f\"Hello {recipient}!\")\n
my_app/templates/my-template.html
In your Django app's HTML template, you can now embed your ReactPy component using the component template tag. Within this tag, you will need to type in the dotted path to the component.
Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous example) accepts a recipient argument.
"},{"location":"learn/your-first-component/","title":"Your First Component","text":""},{"location":"learn/your-first-component/#overview","title":"Overview","text":"
Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!
Note
If you have reached this point, you should have already installed ReactPy-Django through the previous steps.
"},{"location":"learn/your-first-component/#selecting-a-django-app","title":"Selecting a Django App","text":"
You will now need to pick at least one Django app to start using ReactPy-Django on.
For the following examples, we will assume the following:
You have a Django app named my_app, which was created by Django's startapp command.
You have placed my_app directly into your Django project folder (./example_project/my_app). This is common for small projects.
How do I organize my Django project for ReactPy?
ReactPy-Django has no project structure requirements. Organize everything as you wish, just like any Django project.
"},{"location":"learn/your-first-component/#defining-a-component","title":"Defining a component","text":"
You will need a file to start creating ReactPy components.
We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.
Within this file, you can define your component functions using ReactPy's @component decorator.
components.py
from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n return html.h1(f\"Hello {recipient}!\")\n
What should I name my ReactPy files and functions?
You have full freedom in naming/placement of your files and functions.
We recommend creating a components.py for small Django apps. If your app has a lot of components, you should consider breaking them apart into individual modules such as components/navbar.py.
Ultimately, components are referenced by Python dotted path in my-template.html (see next step). This path must be valid to Python's importlib.
What does the decorator actually do?
While not all components need to be decorated, there are a few features this decorator adds to your components.
The ability to be used as a root component.
The decorator is required for any component that you want to reference in your Django templates (see next step).
The ability to use hooks.
The decorator is required on any component where hooks are defined.
Scoped failures.
If a decorated component generates an exception, then only that one component will fail to render.
"},{"location":"learn/your-first-component/#embedding-in-a-template","title":"Embedding in a template","text":"
In your Django app's HTML template, you can now embed your ReactPy component using the {% component %} template tag. Within this tag, you will need to type in the dotted path to the component.
Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous step) accepts a recipient argument.
Do not use context variables for the component path
The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
For example, do not do the following:
my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.
Please note that components separated like this will not be able to interact with each other, except through database queries.
Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.
Where is my templates folder?
If you do not have a ./templates/ folder in your Django app, you can simply create one! Keep in mind, templates within this folder will not be detected by Django unless you add the corresponding Django app to settings.py:INSTALLED_APPS.
"},{"location":"learn/your-first-component/#setting-up-a-django-view","title":"Setting up a Django view","text":"
Within your Django app's views.py file, you will need to create a view function to render the HTML template my-template.html (from the previous step).
views.py
from django.shortcuts import render\n\n\ndef index(request):\n return render(request, \"my-template.html\")\n
We will add this new view into your urls.py and define what URL it should be accessible at.
urls.py
from django.urls import path\nfrom example import views\n\nurlpatterns = [\n path(\"example/\", views.index),\n]\n
Which urls.py do I add my views to?
For simple Django projects, you can easily add all of your views directly into the Django project's urls.py. However, as you start increase your project's complexity you might end up with way too much within one file.
Once you reach that point, we recommend creating an individual urls.py within each of your Django apps.
Then, within your Django project's urls.py you will use Django's include function to link it all together.
"},{"location":"learn/your-first-component/#viewing-your-component","title":"Viewing your component","text":"
To test your new Django view, run the following command to start up a development web server.
python manage.py runserver\n
Now you can navigate to your Django project URL that contains a ReactPy component, such as http://127.0.0.1:8000/example/ (from the previous step).
If you copy-pasted our example component, you will now see your component display \"Hello World\".
Do not use manage.py runserver for production
This command is only intended for development purposes. For production deployments make sure to read Django's documentation.
We supply some pre-designed that components can be used to help simplify development.
"},{"location":"reference/components/#view-to-component","title":"View To Component","text":"
Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.
Name Type Description Default viewCallable | View The view function or class to convert. N/A compatibilitybool If True, the component will be rendered in an iframe. When using compatibility mode tranforms, strict_parsing, request, args, and kwargs arguments will be ignored. FalsetransformsSequence[Callable[[VdomDict], Any]] A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. tuplestrict_parsingbool If True, an exception will be generated if the HTML does not perfectly adhere to HTML5. True
Returns
Type Description _ViewComponentConstructor A function that takes request, *args, key, **kwargs and returns a ReactPy component. All parameters are directly provided to your view, besides key which is used by ReactPy. Potential information exposure when using compatibility = True
When using compatibility mode, ReactPy automatically exposes a URL to your view.
It is your responsibility to ensure privileged information is not leaked via this method.
You must implement a method to ensure only authorized users can access your view. This can be done via directly writing conditionals into your view, or by adding decorators such as user_passes_test to your views. For example...
How do I use strict_parsing, compatibility, and transforms?
strict_parsing
By default, an exception will be generated if your view's HTML does not perfectly adhere to HTML5.
However, there are some circumstances where you may not have control over the original HTML, so you may be unable to fix it. Or you may be relying on non-standard HTML tags such as <my-tag> Hello World </my-tag>.
In these scenarios, you may want to rely on best-fit parsing by setting the strict_parsing parameter to False.
Note: Best-fit parsing is designed to be similar to how web browsers would handle non-standard or broken HTML.
compatibility
For views that rely on HTTP responses other than GET (such as PUT, POST, PATCH, etc), you should consider using compatibility mode to render your view within an iframe.
Any view can be rendered within compatibility mode. However, the transforms, strict_parsing, request, args, and kwargs arguments do not apply to compatibility mode.
Name Type Description Default static_pathstr The path to the static file. This path is identical to what you would use on a static template tag. N/A keyKey | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None
Returns
Type Description Component A ReactPy component. Should I put django_css at the top of my HTML?
Yes, if the stylesheet contains styling for your component.
Can I load static CSS using html.link instead?
While you can load stylesheets with 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.
Here's an example on what you should avoid doing for Django static files:
Name Type Description Default static_pathstr The path to the static file. This path is identical to what you would use on a static template tag. N/A keyKey | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None
Returns
Type Description Component A ReactPy component. Should I put django_js at the bottom of my HTML?
Yes, if your scripts are reliant on the contents of the component.
Can I load static JavaScript using html.script instead?
While you can load JavaScript with 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.
Here's an example on what you should avoid doing for Django static files:
You can limit access to a component to users with a specific auth_attribute by using this decorator (with or without parentheses).
By default, this decorator checks if the user is logged in and not deactivated (is_active).
This decorator is commonly used to selectively render a component only if a user is_staff or is_superuser.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required\ndef my_component():\n return html.div(\"I am logged in!\")\n
See Interface
Parameters
Name Type Description Default auth_attributestr The value to check within the user object. This is checked via getattr(scope[\"user\"], auth_attribute). \"is_active\"fallbackComponentType | VdomDict | None The component or reactpy.html snippet to render if the user is not authenticated. None
Returns
Type Description #!python Component` A ReactPy component. #!python VdomDict| A#!python reactpy.html` snippet. #!python None` No component render. How do I render a different component if authentication fails?
You can use a component with the fallback argument, as seen below.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\ndef my_component_fallback():\n return html.div(\"I am NOT logged in!\")\n\n\n@component\n@auth_required(fallback=my_component_fallback)\ndef my_component():\n return html.div(\"I am logged in!\")\n
How do I render a simple reactpy.html snippet if authentication fails?
You can use a reactpy.html snippet with the fallback argument, as seen below.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(fallback=html.div(\"I am NOT logged in!\"))\ndef my_component():\n return html.div(\"I am logged in!\")\n
How can I check if a user is_staff?
You can do this by setting auth_attribute=\"is_staff\", as seen blow.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_staff\")\ndef my_component():\n return html.div(\"I am logged in!\")\n
How can I check for a custom attribute?
You will need to be using a custom user model within your Django instance.
For example, if your user model has the field is_really_cool ...
models.py
from django.contrib.auth.models import AbstractBaseUser\n\n\nclass CustomUserModel(AbstractBaseUser):\n @property\n def is_really_cool(self):\n return True\n
... then you would do the following within your decorator:
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_really_cool\")\ndef my_component():\n return html.div(\"I am logged in!\")\n
The query function you provide must return either a Model or QuerySet.
components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_query\n\n\ndef get_items():\n return TodoItem.objects.all()\n\n\n@component\ndef todo_list():\n item_query = use_query(get_items)\n\n if item_query.loading:\n rendered_items = html.h2(\"Loading...\")\n elif item_query.error or not item_query.data:\n rendered_items = html.h2(\"Error when loading!\")\n else:\n rendered_items = html.ul([html.li(item, key=item) for item in item_query.data])\n\n return html.div(\"Rendered items: \", rendered_items)\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n text: CharField = CharField(max_length=255)\n
See Interface
Parameters
Name Type Description Default optionsQueryOptions | None An optional QueryOptions object that can modify how the query is executed. NonequeryCallable[_Params, _Result | None] A callable that returns a Django Model or QuerySet. N/A *args_Params.args Positional arguments to pass into query. N/A **kwargs_Params.kwargs Keyword arguments to pass into query. N/A
Returns
Type Description Query[_Result | None] An object containing loading/error states, your data (if the query has successfully executed), and a refetch callable that can be used to re-run the query. How can I provide arguments to my query function?
*args and **kwargs can be provided to your query function via use_query parameters.
Why does get_items in the example return TodoItem.objects.all()?
This was a technical design decision to based on Apollo's useQuery hook, but ultimately helps avoid Django's SynchronousOnlyOperation exceptions.
The use_query hook ensures the provided Model or QuerySet executes all deferred/lazy queries safely prior to reaching your components.
How can I use QueryOptions to customize fetching behavior?
thread_sensitive
Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_thread_safe_operation():\n\"\"\"This is an example query function that does some thread-safe operation.\"\"\"\n pass\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(thread_sensitive=False),\n execute_thread_safe_operation,\n )\n\n if query.loading or query.error:\n return None\n\n return str(query.data)\n
postprocessor
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you...
Want to use this hook to defer IO intensive tasks to be computed in the background
Want to to utilize use_query with a different ORM
... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.
components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n pass\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(postprocessor=None),\n execute_io_intensive_operation,\n )\n\n if query.loading or query.error:\n return None\n\n return str(query.data)\n
If you wish to create a custom postprocessor, you will need to create a callable.
The first argument of postprocessor must be the query data. All proceeding arguments are optional postprocessor_kwargs (see below). This postprocessor must return the modified data.
components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef my_postprocessor(data, example_kwarg=True):\n if example_kwarg:\n return data\n\n return dict(data)\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n pass\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(\n postprocessor=my_postprocessor,\n postprocessor_kwargs={\"example_kwarg\": False},\n ),\n execute_io_intensive_operation,\n )\n\n if query.loading or query.error:\n return None\n\n return str(query.data)\n
postprocessor_kwargs
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.
You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.
components.py
from example.models import TodoItem\nfrom reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef get_model_with_relationships():\n\"\"\"This is an example query function that gets `MyModel` which has a ManyToMany field, and\n additionally other models that have formed a ForeignKey association to `MyModel`.\n\n ManyToMany Field: `many_to_many_field`\n ForeignKey Field: `foreign_key_field_set`\n \"\"\"\n return TodoItem.objects.get(id=1)\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(\n postprocessor_kwargs={\"many_to_many\": False, \"many_to_one\": False}\n ),\n get_model_with_relationships,\n )\n\n if query.loading or query.error or not query.data:\n return None\n\n # By disabling `many_to_many` and `many_to_one`, accessing these fields will now\n # generate a `SynchronousOnlyOperation` exception\n return f\"{query.data.many_to_many_field} {query.data.foriegn_key_field_set}\"\n
Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.
Can I define async query functions?
Async functions are supported by use_query. You can use them in the same way as a sync query function.
However, be mindful of Django async ORM restrictions.
components.py
from channels.db import database_sync_to_async\nfrom example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_query\n\n\nasync def get_items():\n return await database_sync_to_async(TodoItem.objects.all)()\n\n\n@component\ndef todo_list():\n item_query = use_query(get_items)\n\n if item_query.loading:\n rendered_items = html.h2(\"Loading...\")\n elif item_query.error or not item_query.data:\n rendered_items = html.h2(\"Error when loading!\")\n else:\n rendered_items = html.ul([html.li(item, key=item) for item in item_query.data])\n\n return html.div(\"Rendered items: \", rendered_items)\n
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n text: CharField = CharField(max_length=255)\n
See Interface
Parameters
Name Type Description Default mutateCallable[_Params, bool | None] A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used. N/A refetchCallable[..., Any] | Sequence[Callable[..., Any]] | None A query function (used by the use_query hook) or a sequence of query functions that will be called if the mutation succeeds. This is useful for refetching data after a mutation has been performed. None
Returns
Type Description Mutation[_Params] An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query. How can I provide arguments to my mutation function?
*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n text: CharField = CharField(max_length=255)\n
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
This is a shortcut that returns the WebSocket's origin.
You can expect this hook to provide strings such as http://example.com.
components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_origin\n\n\n@component\ndef my_component():\n my_origin = use_origin()\n return html.div(my_origin or \"No origin\")\n
See Interface
Parameters
None
Returns
Type Description str | None A string containing the browser's current origin, obtained from WebSocket headers (if available)."},{"location":"reference/settings/","title":"Settings","text":""},{"location":"reference/settings/#overview","title":"Overview","text":"
These are ReactPy-Django's default settings values. You can modify these values in your Django project's settings.py to change the behavior of ReactPy.
Note
The default configuration of ReactPy is suitable for the vast majority of use cases.
You should only consider changing settings when the necessity arises.
Configures whether ReactPy components are rendered in a dedicated thread.
This setting allows the web server to process other traffic during ReactPy rendering. Vastly improves throughput with web servers such as hypercorn and uvicorn.
Name Type Description Default dotted_pathstr The dotted path to the component to render. N/A *argsAny The positional arguments to provide to the component. N/A classstr | None The HTML class to apply to the top-level component div. NonekeyAny Force the component's root node to use a specific key value. Using key within a template tag is effectively useless. Nonehoststr | None The host to use for the ReactPy connections. If unset, the host will be automatically configured.Example values include: localhost:8000, example.com, example.com/subdirNoneprerenderstr If \"True\", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency. \"False\"**kwargsAny The keyword arguments to provide to the component. N/A
Returns
Type Description Component A ReactPy component. Do not use context variables for the component path
The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
For example, do not do the following:
my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.
Here's a couple of things to keep in mind:
If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
You will not need to register ReactPy HTTP or WebSocket paths on any applications that do not perform any component rendering.
Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?
You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.
Please note that components separated like this will not be able to interact with each other, except through database queries.
Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.
Can I use positional arguments instead of keyword arguments?
You can use any combination of *args/**kwargs in your template tag.
This is the default postprocessor for the use_query hook.
This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n text: CharField = CharField(max_length=255)\n
See Interface
Parameters
Name Type Description Default dataQuerySet | Model The Model or QuerySet to recursively fetch fields from. N/A many_to_manybool Whether or not to recursively fetch ManyToManyField relationships. Truemany_to_onebool Whether or not to recursively fetch ForeignKey relationships. True
Returns
Type Description QuerySet | Model The Model or QuerySet with all fields fetched."},{"location":"reference/utils/#register-component","title":"Register Component","text":"
This function is used manually register a root component with ReactPy.
apps.py
from django.apps import AppConfig\nfrom reactpy_django.utils import register_component\n\n\nclass ExampleConfig(AppConfig):\n def ready(self):\n # Add components to the ReactPy component registry when Django is ready\n register_component(\"example_project.my_app.components.hello_world\")\n
Only use this within MyAppConfig.ready()
You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.
Do I need to use this?
You typically will not need to use this function.
For security reasons, ReactPy does not allow non-registered components to be root components. However, all components contained within Django templates are automatically considered root components.
This is typically only needed when you have a dedicated Django application as a rendering server that doesn't have templates, such as when modifying the template tag host argument. On this dedicated rendering server, you would need to manually register your components.
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"about/changelog/","title":"Changelog","text":"
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Prettier WebSocket URLs for components that do not have sessions.
Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
Bumped the minimum @reactpy/client version to 0.3.1
Bumped the minimum Django version to 4.2.
Use TypeScript instead of JavaScript for this repository.
Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This \"latest-only\" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.
Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.
ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.
django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.
django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.
You will need to set up a Python environment to develop ReactPy-Django.
Note
Looking to contribute features that are not Django specific?
Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.
"},{"location":"about/code/#creating-an-environment","title":"Creating an environment","text":"
If you plan to make code changes to this repository, you will need to install the following dependencies first:
Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.
To learn how to create GitHub PRs, click here.
"},{"location":"about/license/","title":"License","text":""},{"location":"about/license/#the-mit-license-mit","title":"The MIT License (MIT)","text":""},{"location":"about/license/#copyright-c-reactive-python-and-affiliates","title":"Copyright (c) Reactive Python and affiliates.","text":"
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"},{"location":"learn/add-reactpy-to-a-django-project/","title":"Add ReactPy to a Django Project","text":""},{"location":"learn/add-reactpy-to-a-django-project/#overview","title":"Overview","text":"
If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.
Note
These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.
If do not have a Django project, check out this 9 minute YouTube tutorial created by IDG TECHtalk.
"},{"location":"learn/add-reactpy-to-a-django-project/#step-1-install-from-pypi","title":"Step 1: Install from PyPI","text":"
Run the following command to install reactpy-django in your Python environment.
If you do not have an asgi.py, follow the channels installation guide.
"},{"location":"learn/add-reactpy-to-a-django-project/#step-5-run-database-migrations","title":"Step 5: Run database migrations","text":"
Run Django's migrate command to initialize ReactPy-Django's database table.
python manage.py migrate\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-6-check-your-configuration","title":"Step 6: Check your configuration","text":"
Run Django's check command to verify if ReactPy was set up correctly.
python manage.py check\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-7-create-your-first-component","title":"Step 7: Create your first component","text":"
The next step will show you how to create your first ReactPy component.
Prefer a quick summary? Read the At a Glance section below.
At a Glance: Your First Component
my_app/components.py
You will need a file to define your ReactPy components. We recommend creating a components.py file within your chosen Django app to start out. Within this file, we will create a simple hello_world component.
from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n return html.h1(f\"Hello {recipient}!\")\n
my_app/templates/my-template.html
In your Django app's HTML template, you can now embed your ReactPy component using the component template tag. Within this tag, you will need to type in the dotted path to the component.
Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous example) accepts a recipient argument.
"},{"location":"learn/your-first-component/","title":"Your First Component","text":""},{"location":"learn/your-first-component/#overview","title":"Overview","text":"
Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!
Note
If you have reached this point, you should have already installed ReactPy-Django through the previous steps.
"},{"location":"learn/your-first-component/#selecting-a-django-app","title":"Selecting a Django App","text":"
You will now need to pick at least one Django app to start using ReactPy-Django on.
For the following examples, we will assume the following:
You have a Django app named my_app, which was created by Django's startapp command.
You have placed my_app directly into your Django project folder (./example_project/my_app). This is common for small projects.
How do I organize my Django project for ReactPy?
ReactPy-Django has no project structure requirements. Organize everything as you wish, just like any Django project.
"},{"location":"learn/your-first-component/#defining-a-component","title":"Defining a component","text":"
You will need a file to start creating ReactPy components.
We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.
Within this file, you can define your component functions using ReactPy's @component decorator.
components.py
from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n return html.h1(f\"Hello {recipient}!\")\n
What should I name my ReactPy files and functions?
You have full freedom in naming/placement of your files and functions.
We recommend creating a components.py for small Django apps. If your app has a lot of components, you should consider breaking them apart into individual modules such as components/navbar.py.
Ultimately, components are referenced by Python dotted path in my-template.html (see next step). This path must be valid to Python's importlib.
What does the decorator actually do?
While not all components need to be decorated, there are a few features this decorator adds to your components.
The ability to be used as a root component.
The decorator is required for any component that you want to reference in your Django templates (see next step).
The ability to use hooks.
The decorator is required on any component where hooks are defined.
Scoped failures.
If a decorated component generates an exception, then only that one component will fail to render.
"},{"location":"learn/your-first-component/#embedding-in-a-template","title":"Embedding in a template","text":"
In your Django app's HTML template, you can now embed your ReactPy component using the {% component %} template tag. Within this tag, you will need to type in the dotted path to the component.
Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous step) accepts a recipient argument.
Do not use context variables for the component path
The ReactPy component finder requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
For example, do not do the following:
my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.
Please note that components separated like this will not be able to interact with each other, except through database queries.
Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.
Where is my templates folder?
If you do not have a ./templates/ folder in your Django app, you can simply create one! Keep in mind, templates within this folder will not be detected by Django unless you add the corresponding Django app to settings.py:INSTALLED_APPS.
"},{"location":"learn/your-first-component/#setting-up-a-django-view","title":"Setting up a Django view","text":"
Within your Django app's views.py file, you will need to create a view function to render the HTML template my-template.html (from the previous step).
views.py
from django.shortcuts import render\n\n\ndef index(request):\n return render(request, \"my-template.html\")\n
We will add this new view into your urls.py and define what URL it should be accessible at.
urls.py
from django.urls import path\nfrom example import views\n\nurlpatterns = [\n path(\"example/\", views.index),\n]\n
Which urls.py do I add my views to?
For simple Django projects, you can easily add all of your views directly into the Django project's urls.py. However, as you start increase your project's complexity you might end up with way too much within one file.
Once you reach that point, we recommend creating an individual urls.py within each of your Django apps.
Then, within your Django project's urls.py you will use Django's include function to link it all together.
"},{"location":"learn/your-first-component/#viewing-your-component","title":"Viewing your component","text":"
To test your new Django view, run the following command to start up a development web server.
python manage.py runserver\n
Now you can navigate to your Django project URL that contains a ReactPy component, such as http://127.0.0.1:8000/example/ (from the previous step).
If you copy-pasted our example component, you will now see your component display \"Hello World\".
Do not use manage.py runserver for production
This command is only intended for development purposes. For production deployments make sure to read Django's documentation.
We supply some pre-designed that components can be used to help simplify development.
"},{"location":"reference/components/#view-to-component","title":"View To Component","text":"
Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.
Name Type Description Default viewCallable | View The view function or class to convert. N/A compatibilitybool If True, the component will be rendered in an iframe. When using compatibility mode tranforms, strict_parsing, request, args, and kwargs arguments will be ignored. FalsetransformsSequence[Callable[[VdomDict], Any]] A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. tuplestrict_parsingbool If True, an exception will be generated if the HTML does not perfectly adhere to HTML5. True
Returns
Type Description _ViewComponentConstructor A function that takes request, *args, key, **kwargs and returns a ReactPy component. All parameters are directly provided to your view, besides key which is used by ReactPy. Potential information exposure when using compatibility = True
When using compatibility mode, ReactPy automatically exposes a URL to your view.
It is your responsibility to ensure privileged information is not leaked via this method.
You must implement a method to ensure only authorized users can access your view. This can be done via directly writing conditionals into your view, or by adding decorators such as user_passes_test to your views. For example...
How do I use strict_parsing, compatibility, and transforms?
strict_parsing
By default, an exception will be generated if your view's HTML does not perfectly adhere to HTML5.
However, there are some circumstances where you may not have control over the original HTML, so you may be unable to fix it. Or you may be relying on non-standard HTML tags such as <my-tag> Hello World </my-tag>.
In these scenarios, you may want to rely on best-fit parsing by setting the strict_parsing parameter to False.
Note: Best-fit parsing is designed to be similar to how web browsers would handle non-standard or broken HTML.
compatibility
For views that rely on HTTP responses other than GET (such as PUT, POST, PATCH, etc), you should consider using compatibility mode to render your view within an iframe.
Any view can be rendered within compatibility mode. However, the transforms, strict_parsing, request, args, and kwargs arguments do not apply to compatibility mode.
Name Type Description Default static_pathstr The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A keyKey | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None
Returns
Type Description Component A ReactPy component. Can I load static CSS using html.link instead?
While you can load stylesheets with 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.
Here's an example on what you should avoid doing for Django static files:
Name Type Description Default static_pathstr The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A keyKey | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None
Returns
Type Description Component A ReactPy component. Can I load static JavaScript using html.script instead?
While you can load JavaScript with 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.
Here's an example on what you should avoid doing for Django static files:
You can limit component access to users with a specific auth_attribute by using this decorator (with or without parentheses).
By default, this decorator checks if the user is logged in and not deactivated (is_active).
This decorator is commonly used to selectively render a component only if a user is_staff or is_superuser.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required\ndef my_component():\n return html.div(\"I am logged in!\")\n
See Interface
Parameters
Name Type Description Default auth_attributestr The value to check within the user object. This is checked via getattr(scope[\"user\"], auth_attribute). \"is_active\"fallbackComponentType | VdomDict | None The component or reactpy.html snippet to render if the user is not authenticated. None
Returns
Type Description #!python Component` A ReactPy component. #!python VdomDict| A#!python reactpy.html` snippet. #!python None` No component render. How do I render a different component if authentication fails?
You can use a component with the fallback argument, as seen below.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\ndef my_component_fallback():\n return html.div(\"I am NOT logged in!\")\n\n\n@component\n@auth_required(fallback=my_component_fallback)\ndef my_component():\n return html.div(\"I am logged in!\")\n
How do I render a simple reactpy.html snippet if authentication fails?
You can use a reactpy.html snippet with the fallback argument, as seen below.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(fallback=html.div(\"I am NOT logged in!\"))\ndef my_component():\n return html.div(\"I am logged in!\")\n
How can I check if a user is_staff?
You can do this by setting auth_attribute=\"is_staff\", as seen blow.
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_staff\")\ndef my_component():\n return html.div(\"I am logged in!\")\n
How can I check for a custom attribute?
You will need to be using a custom user model within your Django instance.
For example, if your user model has the field is_really_cool ...
models.py
from django.contrib.auth.models import AbstractBaseUser\n\n\nclass CustomUserModel(AbstractBaseUser):\n @property\n def is_really_cool(self):\n return True\n
... then you would do the following within your decorator:
components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_really_cool\")\ndef my_component():\n return html.div(\"I am logged in!\")\n
This hook is used to execute functions in the background and return the result, typically to read data the Django ORM.
The default postprocessor expects your query function to return a Django Model or QuerySet. The postprocessor needs to be changed to execute other types of queries. Query functions can be sync or async.
components.pymodels.py
from channels.db import database_sync_to_async\nfrom example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_query\n\n\nasync def get_items():\n return await database_sync_to_async(TodoItem.objects.all)()\n\n\n@component\ndef todo_list():\n item_query = use_query(get_items)\n\n if item_query.loading:\n rendered_items = html.h2(\"Loading...\")\n elif item_query.error or not item_query.data:\n rendered_items = html.h2(\"Error when loading!\")\n else:\n rendered_items = html.ul([html.li(item, key=item) for item in item_query.data])\n\n return html.div(\"Rendered items: \", rendered_items)\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n text: CharField = CharField(max_length=255)\n
See Interface
Parameters
Name Type Description Default optionsQueryOptions | None An optional QueryOptions object that can modify how the query is executed. NonequeryCallable[_Params, _Result | None] A callable that returns a Django Model or QuerySet. N/A *args_Params.args Positional arguments to pass into query. N/A **kwargs_Params.kwargs Keyword arguments to pass into query. N/A
Returns
Type Description Query[_Result | None] An object containing loading/error states, your data (if the query has successfully executed), and a refetch callable that can be used to re-run the query. How can I provide arguments to my query function?
*args and **kwargs can be provided to your query function via use_query parameters.
This hook accepts a options: QueryOptions parameter that can be used to customize behavior.
Below are the settings that can be modified via these QueryOptions.
thread_sensitive
Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_thread_safe_operation():\n\"\"\"This is an example query function that does some thread-safe operation.\"\"\"\n pass\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(thread_sensitive=False),\n execute_thread_safe_operation,\n )\n\n if query.loading or query.error:\n return None\n\n return str(query.data)\n
postprocessor
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you...
Want to use this hook to defer IO intensive tasks to be computed in the background
Want to to utilize use_query with a different ORM
... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.
components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n pass\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(postprocessor=None),\n execute_io_intensive_operation,\n )\n\n if query.loading or query.error:\n return None\n\n return str(query.data)\n
If you wish to create a custom postprocessor, you will need to create a callable.
The first argument of postprocessor must be the query data. All proceeding arguments are optional postprocessor_kwargs (see below). This postprocessor must return the modified data.
components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef my_postprocessor(data, example_kwarg=True):\n if example_kwarg:\n return data\n\n return dict(data)\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n pass\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(\n postprocessor=my_postprocessor,\n postprocessor_kwargs={\"example_kwarg\": False},\n ),\n execute_io_intensive_operation,\n )\n\n if query.loading or query.error:\n return None\n\n return str(query.data)\n
postprocessor_kwargs
By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.
However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.
You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.
components.py
from example.models import TodoItem\nfrom reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef get_model_with_relationships():\n\"\"\"This is an example query function that gets `MyModel` which has a ManyToMany field, and\n additionally other models that have formed a ForeignKey association to `MyModel`.\n\n ManyToMany Field: `many_to_many_field`\n ForeignKey Field: `foreign_key_field_set`\n \"\"\"\n return TodoItem.objects.get(id=1)\n\n\n@component\ndef my_component():\n query = use_query(\n QueryOptions(\n postprocessor_kwargs={\"many_to_many\": False, \"many_to_one\": False}\n ),\n get_model_with_relationships,\n )\n\n if query.loading or query.error or not query.data:\n return None\n\n # By disabling `many_to_many` and `many_to_one`, accessing these fields will now\n # generate a `SynchronousOnlyOperation` exception\n return f\"{query.data.many_to_many_field} {query.data.foriegn_key_field_set}\"\n
Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
Can I make a failed query try again?
Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.
This hook is used to modify data in the background, typically to create/update/delete data from the Django ORM.
Mutation functions can return False to prevent executing your refetch function. All other returns are ignored. Mutation functions can be sync or async.
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n text: CharField = CharField(max_length=255)\n
See Interface
Parameters
Name Type Description Default mutateCallable[_Params, bool | None] A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used. N/A refetchCallable[..., Any] | Sequence[Callable[..., Any]] | None A query function (the function you provide to your use_query hook) or a sequence of query functions that need a refetch if the mutation succeeds. This is useful for refreshing data after a mutation has been performed. None
Returns
Type Description Mutation[_Params] An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query. How can I provide arguments to my mutation function?
*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.
This hook accepts a options: MutationOptions parameter that can be used to customize behavior.
Below are the settings that can be modified via these MutationOptions.
thread_sensitive
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 sync_to_async docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_mutation\nfrom reactpy_django.types import MutationOptions\n\n\ndef execute_thread_safe_mutation():\n\"\"\"This is an example mutation function that does some thread-safe operation.\"\"\"\n pass\n\n\n@component\ndef my_component():\n item_mutation = use_mutation(\n MutationOptions(thread_sensitive=False),\n execute_thread_safe_mutation,\n )\n\n def submit_event(event):\n if event[\"key\"] == \"Enter\":\n item_mutation.execute(text=event[\"target\"][\"value\"])\n\n if item_mutation.loading or item_mutation.error:\n mutation_status = html.h2(\"Doing something...\")\n elif item_mutation.error:\n mutation_status = html.h2(\"Error!\")\n else:\n mutation_status = html.h2(\"Done.\")\n\n return html.div(\n html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n mutation_status,\n )\n
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.
These 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.
Can I make a failed mutation try again?
Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.
This is a shortcut that returns the client's origin.
You can expect this hook to provide strings such as http://example.com.
components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_origin\n\n\n@component\ndef my_component():\n my_origin = use_origin()\n return html.div(my_origin or \"No origin\")\n
See Interface
Parameters
None
Returns
Type Description str | None A string containing the browser's current origin, obtained from WebSocket or HTTP headers (if available)."},{"location":"reference/settings/","title":"Settings","text":""},{"location":"reference/settings/#overview","title":"Overview","text":"
These are ReactPy-Django's default settings values. You can modify these values in your Django project's settings.py to change the behavior of ReactPy.
Note
The default configuration of ReactPy is suitable for the vast majority of use cases.
You should only consider changing settings when the necessity arises.
Configures whether ReactPy components are rendered in a dedicated thread.
This setting allows the web server to process other traffic during ReactPy rendering. Vastly improves throughput with web servers such as hypercorn and uvicorn.
Name Type Description Default dotted_pathstr The dotted path to the component to render. N/A *argsAny The positional arguments to provide to the component. N/A classstr | None The HTML class to apply to the top-level component div. NonekeyAny Force the component's root node to use a specific key value. Using key within a template tag is effectively useless. Nonehoststr | None The host to use for the ReactPy connections. If unset, the host will be automatically configured.Example values include: localhost:8000, example.com, example.com/subdirNoneprerenderstr If \"True\", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency. \"False\"**kwargsAny The keyword arguments to provide to the component. N/A
Returns
Type Description Component A ReactPy component. Do not use context variables for the component path
The ReactPy component finder requires that your component path is a string.
Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.
For example, do not do the following:
my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.
Here's a couple of things to keep in mind:
If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
You will not need to register ReactPy WebSocket or HTTP paths on any applications that do not perform any component rendering.
Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?
You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.
Please note that components separated like this will not be able to interact with each other, except through database queries.
Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.
Can I use positional arguments instead of keyword arguments?
You can use any combination of *args/**kwargs in your template tag.
This is the default postprocessor for the use_query hook.
This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n text: CharField = CharField(max_length=255)\n
See Interface
Parameters
Name Type Description Default dataQuerySet | Model The Model or QuerySet to recursively fetch fields from. N/A many_to_manybool Whether or not to recursively fetch ManyToManyField relationships. Truemany_to_onebool Whether or not to recursively fetch ForeignKey relationships. True
Returns
Type Description QuerySet | Model The Model or QuerySet with all fields fetched."},{"location":"reference/utils/#register-component","title":"Register Component","text":"
This function is used manually register a root component with ReactPy.
apps.py
from django.apps import AppConfig\nfrom reactpy_django.utils import register_component\n\n\nclass ExampleConfig(AppConfig):\n def ready(self):\n # Add components to the ReactPy component registry when Django is ready\n register_component(\"example_project.my_app.components.hello_world\")\n
Only use this within MyAppConfig.ready()
You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.
Do I need to use this?
You typically will not need to use this function.
For security reasons, ReactPy requires all root components to be registered. However, all components contained within Django templates are automatically registered.
This function is needed when you have configured your host to a dedicated Django rendering application that doesn't have templates.
"}]}
\ No newline at end of file
diff --git a/develop/sitemap.xml b/develop/sitemap.xml
index 9a1c7ecb..8d790b79 100644
--- a/develop/sitemap.xml
+++ b/develop/sitemap.xml
@@ -2,62 +2,67 @@
https://reactive-python.github.io/reactpy-django/develop/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/about/changelog/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/about/code/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/about/docs/
- 2023-09-16
+ 2023-09-21
+ daily
+
+
+ https://reactive-python.github.io/reactpy-django/develop/about/license/
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/learn/add-reactpy-to-a-django-project/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/learn/your-first-component/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/reference/components/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/reference/decorators/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/reference/hooks/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/reference/settings/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/reference/template-tag/
- 2023-09-16
+ 2023-09-21dailyhttps://reactive-python.github.io/reactpy-django/develop/reference/utils/
- 2023-09-16
+ 2023-09-21daily
\ No newline at end of file
diff --git a/develop/sitemap.xml.gz b/develop/sitemap.xml.gz
index 034429c1..5c0e4cbe 100644
Binary files a/develop/sitemap.xml.gz and b/develop/sitemap.xml.gz differ