Skip to content

Template Tag

Overview

Django template tags can be used within your HTML templates to provide ReactPy features.


Component

This template tag can be used to insert any number of server-side ReactPy components onto your page.

Each component loaded via this template tag will receive a dedicated WebSocket connection to the server.

1
2
3
4
5
6
7
{% load reactpy %}
<!DOCTYPE html>
<html>
  <body>
    {% component "example_project.my_app.components.hello_world" recipient="World" %}
  </body>
</html>
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 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"
offline str The dotted path to a component that will be displayed if your root component loses connection to the server. Keep in mind, this offline component will be non-interactive (hooks won't operate). ""
**kwargs Any The keyword arguments to provide to the component. N/A
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 will result in render failures.

For example, do not do the following:

1
2
3
4
5
<!-- This is good -->
{% component "example_project.my_app.components.hello_world" recipient="World" %}

<!-- This is bad -->
{% component my_variable recipient="World" %}
1
2
3
4
5
6
7
8
9
from django.shortcuts import render


def example_view(request):
    return render(
        request,
        "my_template.html",
        context={"my_variable": "example_project.my_app.components.hello_world"},
    )

Note: If you decide to not follow this warning, you will need to use the register_component function to manually register your components.

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
2
3
4
5
6
7
8
9
{% load reactpy %}
<!DOCTYPE html>
<html>
    <body>
        <h1>{% component "example_project.my_app.components.my_title" %}</h1>
        <p>{% component "example_project.my_app_2.components.goodbye_world" class="bold small-font" %}</p>
        {% component "example_project.my_app_3.components.my_button" %}
    </body>
</html>

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.

1
{% component "example_project.my_app.components.frog_greeter" 123 "Mr. Froggles" species="Grey Treefrog" %}
1
2
3
4
5
6
from reactpy import component


@component
def frog_greeter(number, name, species=""):
    return f"Hello #{number}, {name} the {species}!"
Can I render components on a different server (distributed computing)?

Yes! This is most commonly done through settings.py:REACTPY_HOSTS. However, you can use the host keyword to render components on a specific ASGI server.

1
2
3
...
{% component "example_project.my_app.components.do_something" host="127.0.0.1:8001" %}
...

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:

  1. If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
  2. You will not need to register ReactPy WebSocket or HTTP paths on any applications that do not perform any component rendering.
  3. Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
How do I pre-render components for SEO compatibility?

This is most commonly done through settings.py:REACTPY_PRERENDER. However, you can use the prerender keyword to pre-render a specific component.

1
2
3
...
{% component "example_project.my_app.components.do_something" prerender="true" %}
...
How do I display something when the client disconnects?

You can use the offline keyword to display a specific component when the client disconnects from the server.

1
2
3
...
{% component "example_project.my_app.components.do_something" offline="example_project.my_app.components.offline" %}
...

Note: The offline component will be non-interactive (hooks won't operate).

PyScript Component

This template tag can be used to insert any number of client-side ReactPy components onto your page.

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.

 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>
    {% pyscript_component "./example_project/my_app/components/hello_world.py" %}
</body>

</html>
1
2
3
4
5
6
from reactpy import component, html


@component
def root():
    return html.div("Hello, World!")
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"
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!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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.

 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.*.

 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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{% load reactpy %}
<!DOCTYPE html>
<html>

<head>
    <title>ReactPy</title>
    {% pyscript_setup %}
</head>

<body>
    {% pyscript_component "./example_project/my_app/components/root.py"
    "./example_project/my_app/components/child.py" %}
</body>

</html>
1
2
3
4
5
6
7
8
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())
1
2
3
4
5
6
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 string containing raw HTML.

1
2
3
<body>
    {% pyscript_component "./example_project/my_app/components/root.py" initial="<div> Loading ... </div>" %}
</body>

However, you can also insert a reactpy.html snippet or a non-interactive @component via template context.

1
2
3
<body>
    {% pyscript_component "./example_project/my_app/components/root.py" initial=my_initial_object %}
</body>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from django.shortcuts import render
from reactpy import html


def index(request):
    return render(
        request,
        "my_template.html",
        context={"my_initial_object": html.div("Loading ...")},
    )
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.

1
2
3
<body>
    {% pyscript_component "./example_project/my_app/components/main.py" root="main" %}
</body>
1
2
3
4
5
6
from reactpy import component, html


@component
def main():
    return html.div("Hello, World!")

PyScript Setup

This template tag configures the current page to be able to run pyscript.

You can optionally use this tag to configure the current PyScript environment. For example, you can include a list of Python packages to automatically install within the PyScript environment.

1
2
3
4
5
6
{% load reactpy %}

<head>
    <title>ReactPy</title>
    {% pyscript_setup %}
</head>
See Interface

Parameters

Name Type Description Default
*extra_py str Dependencies that need to be loaded on the page for your PyScript components. Each dependency must be contained within it's own string and written in Python requirements file syntax. N/A
extra_js str | dict A JSON string or Python dictionary containing a vanilla JavaScript module URL and the name: str to access it within pyscript.js_modules.*. ""
config str | dict A JSON string or Python dictionary containing PyScript configuration values. ""
How do I install additional Python dependencies?

Dependencies must be available on pypi and declared in your {% pyscript_setup %} block using Python requirements file syntax.

These dependencies are automatically downloaded and installed into the PyScript client-side environment when the page is loaded.

1
2
3
4
<head>
    <title>ReactPy</title>
    {% pyscript_setup "dill==0.3.5" "markdown<=3.6.0" "nest_asyncio" "titlecase" %}
</head>
How do I install additional Javascript dependencies?

You can use the extra_js keyword to load additional JavaScript modules into your PyScript environment.

 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=my_extra_js_object %}
</head>

<body>
    {% component "example_project.my_app.components.root.py" %}
</body>

</html>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from django.shortcuts import render
from django.templatetags.static import static


def index(request):
    return render(
        request,
        "my_template.html",
        context={"my_extra_js_object": {static("moment.js"): "moment"}},
    )

The value for extra_js is most commonly a Python dictionary, but JSON strings are also supported.

 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>
How do I modify the pyscript default configuration?

You can modify the default PyScript configuration by providing a value to the config keyword.

1
2
3
4
<head>
    <title>ReactPy</title>
    {% pyscript_setup config='{"experimental_create_proxy":"auto"}' %}
</head>

While this value is most commonly a JSON string, Python dictionary objects are also supported.

1
2
3
4
<head>
    <title>ReactPy</title>
    {% pyscript_setup config=my_config_object %}
</head>
1
2
3
4
5
6
7
8
9
from django.shortcuts import render


def index(request):
    return render(
        request,
        "my_template.html",
        context={"my_config_object": {"experimental_create_proxy": "auto"}},
    )
Can I use a local interpreter for PyScript?

Yes, you can set up a local interpreter by following PyScript's standard documentation.

To summarize,

  1. Download the latest Pyodide bundle from the Pyodide GitHub releases page (for example pyodide-0.26.3.tar.bz2).
  2. Extract the contents of the bundle to your project's static files.
  3. Configure your {% pyscript_setup %} template tag to use pyodide as an interpreter.

    {% pyscript_setup config='{"interpreter":"/static/pyodide/pyodide.mjs"}' %}
    

Last update: December 19, 2024
Authors: Mark Bakhit