We supply some pre-designed that components can be used to help simplify development.
PyScript Component¶This allows you to embedded any number of client-side PyScript components within traditional ReactPy components.
By default, the only available dependencies are the Python standard library, pyscript
, pyodide
, reactpy
core.
The entire file path provided is loaded directly into the browser, and must have a def root()
component to act as the entry point.
Pitfall
Similar to JavaScript, your provided Python file is loaded directly into the client (web browser) as raw text to run using the PyScript interpreter. Be cautious about what you include in your Python file.
As a result being client-sided, Python packages within your local environment (such as those installed via pip install ...
) are not accessible within PyScript components.
components.pyroot.pymy_template.html
from reactpy import component, html
from reactpy_django.components import pyscript_component
@component
def server_side_component():
return html.div(
"This text is from my server-side component",
pyscript_component("./example_project/my_app/components/root.py"),
)
from reactpy import component, html
@component
def root():
return html.div("This text is from my client-side component")
1 2 3 4 5 6 7 8 9 10 11 12 13 14
{% load reactpy %}
<!DOCTYPE html>
<html>
<head>
<title>ReactPy</title>
{% pyscript_setup %}
</head>
<body>
{% component "example_project.my_app.components.server_side_component" %}
</body>
</html>
See Interface
Parameters
Name Type Description Default*file_paths
str
File path to your client-side component. If multiple paths are provided, the contents are automatically merged. N/A initial
str | VdomDict | ComponentType
The initial HTML that is displayed prior to the PyScript component loads. This can either be a string containing raw HTML, a reactpy.html
snippet, or a non-interactive component. ""
root
str
The name of the root component function. "root"
You must call pyscript_setup
in your Django template before using this tag!
This requires using of the {% pyscript_setup %}
template tag to initialize PyScript on the client.
my_template.html
{% load reactpy %}
<head>
<title>ReactPy</title>
{% pyscript_setup %}
</head>
How do I execute JavaScript within PyScript components?
PyScript components several options available to execute JavaScript, including...
Pyodide JS Module
The Pyodide js
module has access to everything within the browser's JavaScript environment. Therefore, any global JavaScript functions loaded within your HTML <head>
can be called as well. However, you will need to be mindful of JavaScript load order if using async
or deferred
loading!
root.py
import js
from reactpy import component, html
@component
def root():
def on_click(event):
js.document.title = "New window title"
return html.button({"onClick": on_click}, "Click Me!")
PyScript Foreign Function Interface (FFI)
PyScript FFI has similar functionality to Pyodide's js
module, but utilizes a different API.
There are two importable modules available that are available within the FFI interface: window
and document
.
root.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from pyscript import document, window
from reactpy import component, html
@component
def root():
def on_click(event):
my_element = document.querySelector("#example")
my_element.innerText = window.location.hostname
return html.div(
{"id": "example"},
html.button({"onClick": on_click}, "Click Me!"),
)
PyScript JS Modules
Assuming you have a local bundle stored within your project's static files, you can import JavaScript modules in a fashion similar to import {moment} from 'static/moment.js'
. You will first need to configure your {% pyscript_setup %}
block to make the moment.js
module available to PyScript. Then, this module can be accessed within pyscript.js_modules.*
.
root.pymy_template.html
1 2 3 4 5 6 7 8 9 10 11 12
from reactpy import component, html
@component
def root():
from pyscript.js_modules import moment
return html.div(
{"id": "moment"},
"Using the JavaScript package 'moment' to calculate time: ",
moment.default().format("YYYY-MM-DD HH:mm:ss"),
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
{% load reactpy %}
<!DOCTYPE html>
<html>
<head>
<title>ReactPy</title>
{% pyscript_setup extra_js='{"/static/moment.js":"moment"}' %}
</head>
<body>
{% component "example_project.my_app.components.root.py" %}
</body>
</html>
Does my entire component need to be contained in one file?
Splitting a large file into multiple files is a common practice in software development.
However, PyScript components are run on the client browser. As such, they do not have access to your local development environment, and thus cannot import
any local Python files.
If your PyScript component file gets too large, you can declare multiple file paths instead. These files will automatically combined by ReactPy.
Here is how we recommend splitting your component into multiple files while avoiding local imports but retaining type hints.
components.pyroot.pychild.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from reactpy_django.components import pyscript_component
@component
def server_side_component():
return html.div(
pyscript_component(
"./example_project/my_app/components/root.py",
"./example_project/my_app/components/child.py",
),
)
from reactpy import component, html
from example.components import child_component
@component
def root():
return html.div("This text is from the root component.", child_component())
from reactpy import component, html
@component
def child_component():
return html.div("This is a child component from a different file.")
How do I display something while the component is loading?
You can configure the initial
keyword to display HTML while your PyScript component is loading.
The value for initial
is most commonly be a reactpy.html
snippet or a non-interactive @component
.
components.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from reactpy_django.components import pyscript_component
@component
def server_side_component():
return html.div(
pyscript_component(
"./example_project/my_app/components/root.py",
initial=html.div("Loading ..."),
),
)
However, you can also use a string containing raw HTML.
components.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from reactpy_django.components import pyscript_component
@component
def server_side_component():
return html.div(
pyscript_component(
"./example_project/my_app/components/root.py",
initial="<div> Loading ... </div>",
),
)
Can I use a different name for my root component?
Yes, you can use the root
keyword to specify a different name for your root function.
components.pymain.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from reactpy_django.components import pyscript_component
@component
def server_side_component():
return html.div(
pyscript_component(
"./example_project/my_app/components/main.py",
root="main",
),
)
from reactpy import component, html
@component
def main():
return html.div("Hello, World!")
View To Component¶
Automatically convert a Django view into a component.
At this time, this works best with static views with no interactivity.
Compatible with sync or async Function Based Views and Class Based Views.
components.pyviews.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_component
hello_world_component = view_to_component(views.hello_world)
@component
def my_component():
return html.div(
hello_world_component(),
)
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello World!")
See Interface
Parameters
Name Type Description Defaultview
Callable | View | str
The view to convert, or the view's dotted path as a string. N/A transforms
Sequence[Callable[[VdomDict], Any]]
A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. tuple
strict_parsing
bool
If True
, an exception will be generated if the HTML does not perfectly adhere to HTML5. True
Returns
Type Descriptionconstructor
A function that takes request, *args, key, **kwargs
and returns a ReactPy component. Note that *args
and **kwargs
are directly provided to your view. Existing limitations
There are currently several limitations of using view_to_component
that will be resolved in a future version.
GET
.<a href='example/'></a>
).Class Based Views are accepted by view_to_component
as an argument.
Calling as_view()
is optional, but recommended.
components.pyviews.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_component
hello_world_component = view_to_component(views.HelloWorld.as_view())
@component
def my_component():
return html.div(
hello_world_component(),
)
from django.http import HttpResponse
from django.views import View
class HelloWorld(View):
def get(self, request):
return HttpResponse("Hello World!")
How do I provide request
, args
, and kwargs
to a converted view?
This component accepts request
, *args
, and **kwargs
arguments, which are sent to your provided view.
components.pyviews.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
from django.http import HttpRequest
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_component
hello_world_component = view_to_component(views.hello_world)
@component
def my_component():
request = HttpRequest()
request.method = "GET"
return html.div(
hello_world_component(
request, # This request object is optional.
"value_1",
"value_2",
kwarg1="abc",
kwarg2="123",
),
)
from django.http import HttpResponse
def hello_world(request, arg1, arg2, kwarg1=None, kwarg2=None):
return HttpResponse(f"Hello World! {arg1} {arg2} {kwarg1} {kwarg2}")
How do I customize this component's behavior?
This component accepts arguments that can be used to customize its behavior.
Below are all the arguments that can be used.
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
. This uses libxml2
recovery algorithm, which is designed to be similar to how web browsers would attempt to parse non-standard or broken HTML.
components.pyviews.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_component
hello_world_component = view_to_component(views.hello_world)
@component
def my_component():
return html.div(
hello_world_component(),
)
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello World!")
transforms
After your view has been turned into VDOM (python dictionaries), view_to_component
will call your transforms
functions on every VDOM node.
This allows you to modify your view prior to rendering.
For example, if you are trying to modify the text of a node with a certain id
, you can create a transform like such:
components.pyviews.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_component
def example_transform(vdom):
attributes = vdom.get("attributes")
if attributes and attributes.get("id") == "hello-world":
vdom["children"][0] = "Farewell World!"
hello_world_component = view_to_component(views.hello_world, transforms=[example_transform])
@component
def my_component():
return html.div(
hello_world_component(),
)
from django.http import HttpResponse
def hello_world(request):
return HttpResponse('<div id="hello-world"> Hello World! </div>')
View To Iframe¶
Automatically convert a Django view into an iframe
element.
The contents of this iframe
is handled entirely by traditional Django view rendering. While this solution is compatible with more views than view_to_component
, it comes with different limitations.
Compatible with sync or async Function Based Views and Class Based Views.
components.pyviews.pyapps.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_iframe
hello_world_iframe = view_to_iframe(views.hello_world)
@component
def my_component():
return html.div(
hello_world_iframe(),
)
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello World!")
from django.apps import AppConfig
from example import views
from reactpy_django.utils import register_iframe
class ExampleAppConfig(AppConfig):
name = "example"
def ready(self):
register_iframe(views.hello_world)
See Interface
Parameters
Name Type Description Defaultview
Callable | View | str
The view function or class to convert. N/A extra_props
Mapping[str, Any] | None
Additional properties to add to the iframe
element. None
Returns
Type Descriptionconstructor
A function that takes *args, key, **kwargs
and returns a ReactPy component. Note that *args
and **kwargs
are directly provided to your view. Existing limitations
There are currently several limitations of using view_to_iframe
which may be resolved in a future version.
args
and kwargs
must be serializable values, since they are encoded into the URL.iframe
will always load after the parent component.iframe
elements tends to be awkward.Class Based Views are accepted by view_to_iframe
as an argument.
Calling as_view()
is optional, but recommended.
components.pyviews.pyapps.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_iframe
hello_world_iframe = view_to_iframe(views.HelloWorld.as_view())
@component
def my_component():
return html.div(
hello_world_iframe(),
)
from django.http import HttpResponse
from django.views import View
class HelloWorld(View):
def get(self, request):
return HttpResponse("Hello World!")
from django.apps import AppConfig
from example import views
from reactpy_django.utils import register_iframe
class ExampleAppConfig(AppConfig):
name = "example"
def ready(self):
register_iframe(views.HelloWorld)
How do I provide args
and kwargs
to a converted view?
This component accepts *args
and **kwargs
arguments, which are sent to your provided view.
All provided *args
and *kwargs
must be serializable values, since they are encoded into the URL.
components.pyviews.pyapps.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_iframe
hello_world_iframe = view_to_iframe(
views.hello_world,
)
@component
def my_component():
return html.div(
hello_world_iframe(
"value_1",
"value_2",
kwarg1="abc",
kwarg2="123",
),
)
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello World!")
from django.apps import AppConfig
from example import views
from reactpy_django.utils import register_iframe
class ExampleAppConfig(AppConfig):
name = "example"
def ready(self):
register_iframe(views.hello_world)
How do I customize this component's behavior?
This component accepts arguments that can be used to customize its behavior.
Below are all the arguments that can be used.
extra_props
This component accepts a extra_props
parameter, which is a dictionary of additional properties to add to the iframe
element.
For example, if you want to add a title
attribute to the iframe
element, you can do so like such:
components.pyviews.pyapps.py
1 2 3 4 5 6 7 8 9 10 11 12 13
from reactpy import component, html
from example import views
from reactpy_django.components import view_to_iframe
hello_world_iframe = view_to_iframe(views.hello_world, extra_props={"title": "Hello World!"})
@component
def my_component():
return html.div(
hello_world_iframe(),
)
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello World!")
from django.apps import AppConfig
from example import views
from reactpy_django.utils import register_iframe
class ExampleAppConfig(AppConfig):
name = "example"
def ready(self):
register_iframe(views.hello_world)
Django Form¶
Automatically convert a Django form into a ReactPy component.
Compatible with both standard Django forms and ModelForms.
components.pyforms.py
from reactpy import component, html
from example.forms import MyForm
from reactpy_django.components import django_form
@component
def basic_form():
children = [html.input({"type": "submit"})]
return django_form(MyForm, bottom_children=children)
from django import forms
class MyForm(forms.Form):
username = forms.CharField(label="Username")
See Interface
Parameters
Name Type Description Defaultform
type[Form | ModelForm]
The form to convert. N/A on_success
AsyncFormEvent | SyncFormEvent | None
A callback function that is called when the form is successfully submitted. None
on_error
AsyncFormEvent | SyncFormEvent | None
A callback function that is called when the form submission fails. None
on_receive_data
AsyncFormEvent | SyncFormEvent | None
A callback function that is called before newly submitted form data is rendered. None
on_change
AsyncFormEvent | SyncFormEvent | None
A callback function that is called when a form field is modified by the user. None
auto_save
bool
If True
, the form will automatically call save
on successful submission of a ModelForm
. This has no effect on regular Form
instances. True
extra_props
dict[str, Any] | None
Additional properties to add to the <form>
element. None
extra_transforms
Sequence[Callable[[VdomDict], Any]] | None
A list of functions that transforms the newly generated VDOM. The functions will be repeatedly called on each VDOM node. None
form_template
str | None
The template to use for the form. If None
, Django's default template is used. None
thread_sensitive
bool
Whether to run event callback functions in thread sensitive mode. This mode only applies to sync functions, and is turned on by default due to Django ORM limitations. True
top_children
Sequence[Any]
Additional elements to add to the top of the form. tuple
bottom_children
Sequence[Any]
Additional elements to add to the bottom of the form. tuple
key
Key | None
A key to uniquely identify this component which is unique amongst a component's immediate siblings. None
Returns
Type DescriptionComponent
A ReactPy component. Existing limitations
The following fields are currently incompatible with django_form
: FileField
, ImageField
, SplitDateTimeField
, and MultiValueField
.
Compatibility for these fields will be added in a future version.
How do I style these forms with Bootstrap?You can style these forms by using a form styling library. In the example below, it is assumed that you have already installed django-bootstrap5
.
After installing a form styling library, you can then provide ReactPy a custom form_template
parameter. This parameter allows you to specify a custom HTML template to use to render this the form.
Note that you can also set a global default for form_template
by using settings.py:REACTPY_DEFAULT_FORM_TEMPLATE
.
components.pyforms.pybootstrap_form.html
from reactpy import component
from example.forms import MyForm
from reactpy_django.components import django_form
@component
def basic_form():
return django_form(MyForm, form_template="bootstrap_form.html")
from django import forms
class MyForm(forms.Form):
username = forms.CharField(label="Username")
{% load django_bootstrap5 %}
<!-- Note: CSS/JS is loaded here only for demonstration purposes.
You should load this CSS/JS in your HTML <head> instead. -->
{% bootstrap_css %}
{% bootstrap_javascript %}
<!-- The actual form that is rendered by ReactPy -->
{% bootstrap_form form %}
{% bootstrap_button button_type="submit" content="OK" %}
{% bootstrap_button button_type="reset" content="Reset" %}
How do I handle form success/errors?
You can react to form state by providing a callback function to any of the following parameters: on_success
, on_error
, on_receive_data
, and on_change
.
These functions will be called when the form is submitted.
In the example below, we will use the on_success
parameter to change the URL upon successful submission.
components.pyforms.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
from reactpy import component, hooks, html
from reactpy_router import navigate
from example.forms import MyForm
from reactpy_django.components import django_form
from reactpy_django.types import FormEventData
@component
def basic_form():
submitted, set_submitted = hooks.use_state(False)
def on_submit(event: FormEventData):
"""This function will be called when the form is successfully submitted."""
set_submitted(True)
if submitted:
return navigate("/homepage")
children = [html.input({"type": "submit"})]
return django_form(MyForm, on_success=on_submit, bottom_children=children)
from django import forms
class MyForm(forms.Form):
username = forms.CharField(label="Username")
Django CSS¶
Allows you to defer loading a CSS stylesheet until a component begins rendering. This stylesheet must be stored within Django's static files.
components.py
from reactpy import component, html
from reactpy_django.components import django_css
@component
def my_component():
return html.div(
django_css("css/buttons.css"),
html.button("My Button!"),
)
See Interface
Parameters
Name Type Description Defaultstatic_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 DescriptionComponent
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:
from django.templatetags.static import static
from reactpy import component, html
@component
def my_component():
return html.div(
html.link({"rel": "stylesheet", "href": static("css/buttons.css")}),
html.button("My Button!"),
)
How do I load external CSS?
django_css
can only be used with local static files.
For external CSS, you should use html.link
.
from reactpy import component, html
@component
def my_component():
return html.div(
html.link({"rel": "stylesheet", "href": "https://example.com/external-styles.css"}),
html.button("My Button!"),
)
Why not load my CSS in <head>
?
Traditionally, stylesheets are loaded in your <head>
using Django's {% static %}
template tag.
However, to help improve webpage load times you can use this django_css
component to defer loading your stylesheet until it is needed.
Allows you to defer loading JavaScript until a component begins rendering. This JavaScript must be stored within Django's static files.
components.py
from reactpy import component, html
from reactpy_django.components import django_js
@component
def my_component():
return html.div(
html.button("My Button!"),
django_js("js/scripts.js"),
)
See Interface
Parameters
Name Type Description Defaultstatic_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 DescriptionComponent
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:
from django.templatetags.static import static
from reactpy import component, html
@component
def my_component():
return html.div(
html.script({"src": static("js/scripts.js")}),
html.button("My Button!"),
)
How do I load external JS?
django_js
can only be used with local static files.
For external JavaScript, you should use html.script
.
from reactpy import component, html
@component
def my_component():
return html.div(
html.script({"src": "https://example.com/external-scripts.js"}),
html.button("My Button!"),
)
Why not load my JS in <head>
?
Traditionally, JavaScript is loaded in your <head>
using Django's {% static %}
template tag.
However, to help improve webpage load times you can use this django_js
component to defer loading your JavaScript until it is needed.
Last update: December 11, 2024
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4