Skip to content

Commit

Permalink
Client-side Python components using PyScript (#243)
Browse files Browse the repository at this point in the history
-   Client-side Python components can now be rendered via the new `{% pyscript_component %}` template tag
    -   You must first call the `{% pyscript_setup %}` template tag to load PyScript dependencies
-   Client-side components can be embedded into existing server-side components via `reactpy_django.components.pyscript_component`.
-   Tired of writing JavaScript? You can now write PyScript code that runs directly within client browser via the `reactpy_django.html.pyscript` element.
    -   This is a viable substitution for most JavaScript code.
  • Loading branch information
Archmonger authored Jun 22, 2024
1 parent 2e343aa commit fb6c258
Show file tree
Hide file tree
Showing 80 changed files with 7,395 additions and 183 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ReactPy-Django Build Artifacts
src/reactpy_django/static/*
src/reactpy_django/static/reactpy_django/client.js
src/reactpy_django/static/reactpy_django/pyscript
src/reactpy_django/static/reactpy_django/morphdom

# Django #
logs
Expand Down
18 changes: 15 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,33 @@ Using the following categories, list your changes in this order:

## [Unreleased]

### Added

- Client-side Python components can now be rendered via the new `{% pyscript_component %}` template tag
- You must first call the `{% pyscript_setup %}` template tag to load PyScript dependencies
- Client-side components can be embedded into existing server-side components via `reactpy_django.components.pyscript_component`.
- Tired of writing JavaScript? You can now write PyScript code that runs directly within client browser via the `reactpy_django.html.pyscript` element.
- This is a viable substitution for most JavaScript code.

### Changed

- New syntax for `use_query` and `use_mutation` hooks. Here's a quick comparison of the changes:

```python
query = use_query(QueryOptions(thread_sensitive=True), get_items, value=123456, foo="bar") # Old
query = use_query(get_items, {"value":12356, "foo":"bar"}, thread_sensitive=True) # New
query = use_query(QueryOptions(thread_sensitive=True), get_items, foo="bar") # Old
query = use_query(get_items, {"foo":"bar"}, thread_sensitive=True) # New

mutation = use_mutation(MutationOptions(thread_sensitive=True), remove_item) # Old
mutation = use_mutation(remove_item, thread_sensitive=True) # New
```

### Removed

- `QueryOptions` and `MutationOptions` have been removed. Their values are now passed direct into the hook.
- `QueryOptions` and `MutationOptions` have been removed. The value contained within these objects are now passed directly into the hook.

### Fixed

- Resolved a bug where Django-ReactPy would not properly detect `settings.py:DEBUG`.

## [3.8.1] - 2024-05-07

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# <img src="https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-square.svg" align="left" height="45"/> ReactPy Django
# <img src="https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-square.svg" align="left" height="45"/> ReactPy-Django

<p>
<a href="https://github.com/reactive-python/reactpy-django/actions?query=workflow%3ATest">
Expand All @@ -21,6 +21,7 @@
[ReactPy-Django](https://github.com/reactive-python/reactpy-django) is used to add [ReactPy](https://reactpy.dev/) support to an existing **Django project**. This package also turbocharges ReactPy with features such as...

- [SEO compatible rendering](https://reactive-python.github.io/reactpy-django/latest/reference/settings/#reactpy_prerender)
- [Client-Side Python components](https://reactive-python.github.io/reactpy-django/latest/reference/template-tag/#pyscript-component)
- [Single page application (SPA) capabilities](https://reactive-python.github.io/reactpy-django/latest/reference/router/#django-router)
- [Distributed computing](https://reactive-python.github.io/reactpy-django/latest/reference/settings/#reactpy_default_hosts)
- [Performance enhancements](https://reactive-python.github.io/reactpy-django/latest/reference/settings/#performance-settings)
Expand Down Expand Up @@ -82,7 +83,7 @@ def hello_world(recipient: str):

<!--py-code-end-->

## [`my_app/templates/my-template.html`](https://docs.djangoproject.com/en/dev/topics/templates/)
## [`my_app/templates/my_template.html`](https://docs.djangoproject.com/en/dev/topics/templates/)

<!--html-header-start-->

Expand Down
14 changes: 14 additions & 0 deletions docs/examples/html/pyscript-component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,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>
3 changes: 3 additions & 0 deletions docs/examples/html/pyscript-initial-object.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<body>
{% pyscript_component "./example_project/my_app/components/root.py" initial=my_initial_object %}
</body>
3 changes: 3 additions & 0 deletions docs/examples/html/pyscript-initial-string.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<body>
{% pyscript_component "./example_project/my_app/components/root.py" initial="<div> Loading ... </div>" %}
</body>
14 changes: 14 additions & 0 deletions docs/examples/html/pyscript-js-module.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,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>
15 changes: 15 additions & 0 deletions docs/examples/html/pyscript-multiple-files.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,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>
3 changes: 3 additions & 0 deletions docs/examples/html/pyscript-root.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<body>
{% pyscript_component "./example_project/my_app/components/main.py" root="main" %}
</body>
4 changes: 4 additions & 0 deletions docs/examples/html/pyscript-setup-config-object.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<head>
<title>ReactPy</title>
{% pyscript_setup config=my_config_object %}
</head>
4 changes: 4 additions & 0 deletions docs/examples/html/pyscript-setup-config-string.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<head>
<title>ReactPy</title>
{% pyscript_setup config='{"experimental_create_proxy":"auto"}' %}
</head>
4 changes: 4 additions & 0 deletions docs/examples/html/pyscript-setup-dependencies.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<head>
<title>ReactPy</title>
{% pyscript_setup "dill==0.3.5" "markdown<=3.6.0" "nest_asyncio" "titlecase" %}
</head>
14 changes: 14 additions & 0 deletions docs/examples/html/pyscript-setup-extra-js-object.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,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>
14 changes: 14 additions & 0 deletions docs/examples/html/pyscript-setup-extra-js-string.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,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>
6 changes: 6 additions & 0 deletions docs/examples/html/pyscript-setup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% load reactpy %}

<head>
<title>ReactPy</title>
{% pyscript_setup %}
</head>
14 changes: 14 additions & 0 deletions docs/examples/html/pyscript-ssr-parent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,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>
14 changes: 14 additions & 0 deletions docs/examples/html/pyscript-tag.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% load reactpy %}
<!DOCTYPE html>
<html>

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

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

</html>
2 changes: 1 addition & 1 deletion docs/examples/python/example/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


def index(request):
return render(request, "my-template.html")
return render(request, "my_template.html")
12 changes: 12 additions & 0 deletions docs/examples/python/pyscript-component-initial-object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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 ..."),
),
)
12 changes: 12 additions & 0 deletions docs/examples/python/pyscript-component-initial-string.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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>",
),
)
12 changes: 12 additions & 0 deletions docs/examples/python/pyscript-component-multiple-files-root.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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",
),
)
12 changes: 12 additions & 0 deletions docs/examples/python/pyscript-component-root.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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",
),
)
6 changes: 6 additions & 0 deletions docs/examples/python/pyscript-hello-world.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from reactpy import component, html


@component
def root():
return html.div("Hello, World!")
10 changes: 10 additions & 0 deletions docs/examples/python/pyscript-initial-object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,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 ...")},
)
11 changes: 11 additions & 0 deletions docs/examples/python/pyscript-js-execution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import js
from reactpy import component, html


@component
def root():

def onClick(event):
js.document.title = "New window title"

return html.button({"onClick": onClick}, "Click Me!")
12 changes: 12 additions & 0 deletions docs/examples/python/pyscript-js-module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,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"),
)
6 changes: 6 additions & 0 deletions docs/examples/python/pyscript-multiple-files-child.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from reactpy import component, html


@component
def child_component():
return html.div("This is a child component from a different file.")
11 changes: 11 additions & 0 deletions docs/examples/python/pyscript-multiple-files-root.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from typing import TYPE_CHECKING

from reactpy import component, html

if TYPE_CHECKING:
from .child import child_component


@component
def root():
return html.div("This text is from the root component.", child_component())
6 changes: 6 additions & 0 deletions docs/examples/python/pyscript-root.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from reactpy import component, html


@component
def main():
return html.div("Hello, World!")
9 changes: 9 additions & 0 deletions docs/examples/python/pyscript-setup-config-object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.shortcuts import render


def index(request):
return render(
request,
"my_template.html",
context={"my_config_object": {"experimental_create_proxy": "auto"}},
)
10 changes: 10 additions & 0 deletions docs/examples/python/pyscript-setup-extra-js-object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,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"}},
)
6 changes: 6 additions & 0 deletions docs/examples/python/pyscript-ssr-child.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from reactpy import component, html


@component
def root():
return html.div("This text is from my client-side component")
10 changes: 10 additions & 0 deletions docs/examples/python/pyscript-ssr-parent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
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"),
)
15 changes: 15 additions & 0 deletions docs/examples/python/pyscript-tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from reactpy import component, html
from reactpy_django.html import pyscript

example_source_code = """
import js
js.console.log("Hello, World!")
"""


@component
def server_side_component():
return html.div(
pyscript(example_source_code.strip()),
)
Loading

0 comments on commit fb6c258

Please sign in to comment.