|
1 | | -# Django IDOM · [](https://github.com/idom-team/django-idom/actions?query=workflow%3ATest) [](https://pypi.python.org/pypi/django-idom) [](https://github.com/idom-team/django-idom/blob/main/LICENSE) |
2 | | - |
3 | | -`django-idom` allows Django to integrate with [IDOM](https://github.com/idom-team/idom), a reactive Python web framework for building **interactive websites without needing a single line of Javascript**. |
4 | | - |
5 | | -**You can try IDOM now in a Jupyter Notebook:** |
6 | | -<a |
7 | | - target="_blank" |
8 | | - href="https://mybinder.org/v2/gh/idom-team/idom-jupyter/main?filepath=notebooks%2Fintroduction.ipynb"> |
9 | | -<img |
10 | | - alt="Binder" |
11 | | - valign="bottom" |
12 | | - height="21px" |
13 | | - src="https://mybinder.org/badge_logo.svg"/> |
14 | | -</a> |
15 | | - |
16 | | -# Quick Example |
17 | | - |
18 | | -## `example_app/components.py` |
19 | | - |
20 | | -This is where you'll define your [IDOM](https://github.com/idom-team/idom) components. Ultimately though, you should |
21 | | -feel free to organize your component modules as you wish. Any components created will ultimately be referenced |
22 | | -by Python dotted path in `your-template.html`. |
23 | | - |
24 | | -```python |
25 | | -from idom import component, html |
26 | | -from django_idom import IdomWebsocket |
27 | | - |
28 | | -# Components are CamelCase by ReactJS convention |
29 | | -@component |
30 | | -def Hello(websocket: IdomWebsocket, greeting_recipient: str): |
31 | | - return html.h1(f"Hello {greeting_recipient}!") |
32 | | -``` |
33 | | - |
34 | | -## [`example_app/templates/your-template.html`](https://docs.djangoproject.com/en/dev/topics/templates/) |
35 | | - |
36 | | -In your templates, you may add IDOM components into your HTML by using the `idom_component` |
37 | | -template tag. This tag requires the dotted path to the component function. |
38 | | - |
39 | | -Additonally, you can pass in keyworded arguments into your component function. |
40 | | - |
41 | | -In context this will look a bit like the following... |
42 | | - |
43 | | -```jinja |
44 | | -{% load idom %} |
45 | | -
|
46 | | -<!DOCTYPE html> |
47 | | -<html> |
48 | | - <head> |
49 | | - <title>Example Project</title> |
50 | | - </head> |
51 | | -
|
52 | | - <body> |
53 | | - {% idom_component "my_django_project.example_app.components.Hello" greeting_recipient="World" %} |
54 | | - </body> |
55 | | -</html> |
56 | | -``` |
57 | | - |
58 | | -# Installation |
59 | | - |
60 | | -Install `django-idom` via pip. |
| 1 | +<!--header-start--> |
61 | 2 |
|
62 | | -```bash |
63 | | -pip install django-idom |
64 | | -``` |
65 | | - |
66 | | -You'll also need to modify a few files in your Django project. |
67 | | - |
68 | | -## [`settings.py`](https://docs.djangoproject.com/en/dev/topics/settings/) |
69 | | - |
70 | | -In your settings you'll need to add `channels` and `django_idom` to [`INSTALLED_APPS`](https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-INSTALLED_APPS). |
71 | | - |
72 | | -```python |
73 | | -INSTALLED_APPS = [ |
74 | | - ..., |
75 | | - "channels", |
76 | | - "django_idom", |
77 | | -] |
78 | | - |
79 | | -# Ensure ASGI_APPLICATION is set properly based on your project name! |
80 | | -ASGI_APPLICATION = "my_django_project.asgi.application" |
81 | | -``` |
82 | | - |
83 | | -**Optional:** You can also configure IDOM settings. |
| 3 | +# Django IDOM · [](https://github.com/idom-team/django-idom/actions?query=workflow%3ATest) [](https://pypi.python.org/pypi/django-idom) [](https://github.com/idom-team/django-idom/blob/main/LICENSE) |
84 | 4 |
|
85 | | -```python |
86 | | -# If "idom" cache is not configured, then we'll use "default" instead |
87 | | -CACHES = { |
88 | | - "idom": {"BACKEND": ...}, |
89 | | -} |
| 5 | +<!--header-end--> |
| 6 | +<!--intro-start--> |
90 | 7 |
|
91 | | -# Maximum seconds between two reconnection attempts that would cause the client give up. |
92 | | -# 0 will disable reconnection. |
93 | | -IDOM_WS_MAX_RECONNECT_TIMEOUT: int = 604800 |
| 8 | +Django-IDOM connects your project to a ReactJS frontend, allowing you to create **interactive websites without needing JavaScript!** |
94 | 9 |
|
95 | | -# The URL for IDOM to serve websockets |
96 | | -IDOM_WEBSOCKET_URL: str = "idom/" |
97 | | -``` |
| 10 | +Following ReactJS styling, web elements are combined into [reusable "components"](https://idom-docs.herokuapp.com/docs/guides/creating-interfaces/your-first-components/index.html#parametrizing-components). These components can utilize [hooks](https://idom-docs.herokuapp.com/docs/reference/hooks-api.html) and [events](https://idom-docs.herokuapp.com/docs/guides/adding-interactivity/responding-to-events/index.html#async-event-handlers) to create infinitely complex web pages. |
98 | 11 |
|
99 | | -## [`urls.py`](https://docs.djangoproject.com/en/dev/topics/http/urls/) |
| 12 | +When needed, IDOM can [use components directly from NPM](https://idom-docs.herokuapp.com/docs/guides/escape-hatches/javascript-components.html#dynamically-loaded-components). For additional flexibility, components can also be [fully developed in JavaScript](https://idom-docs.herokuapp.com/docs/guides/escape-hatches/javascript-components.html#custom-javascript-components). |
100 | 13 |
|
101 | | -Add IDOM HTTP paths to your `urlpatterns`. |
| 14 | +Any Python web framework with Websockets can support IDOM. See below for what frameworks are supported out of the box. |
102 | 15 |
|
103 | | -```python |
104 | | -from django.urls import include, path |
| 16 | +| Supported Frameworks | Supported Frameworks (External) | |
| 17 | +| ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 18 | +| [`Flask`, `FastAPI`, `Sanic`, `Tornado`](https://idom-docs.herokuapp.com/docs/guides/getting-started/installing-idom.html#officially-supported-servers) | [`Django`](https://github.com/idom-team/django-idom), [`Plotly-Dash`](https://github.com/idom-team/idom-dash), [`Jupyter`](https://github.com/idom-team/idom-jupyter) | |
105 | 19 |
|
106 | | -urlpatterns = [ |
107 | | - path("idom/", include("django_idom.http.urls")), |
108 | | - ... |
109 | | -] |
110 | | -``` |
| 20 | +<!--intro-end--> |
111 | 21 |
|
112 | | -## [`asgi.py`](https://docs.djangoproject.com/en/dev/howto/deployment/asgi/) |
| 22 | +--- |
113 | 23 |
|
114 | | -Register IDOM's websocket using `IDOM_WEBSOCKET_PATH`. |
| 24 | +# At a Glance |
115 | 25 |
|
116 | | -_Note: If you do not have an `asgi.py`, follow the [`channels` installation guide](https://channels.readthedocs.io/en/stable/installation.html)._ |
| 26 | +## `my_app/components.py` |
117 | 27 |
|
118 | | -```python |
| 28 | +<!--py-header-start--> |
119 | 29 |
|
120 | | -import os |
121 | | -from django.core.asgi import get_asgi_application |
| 30 | +You'll need a file to define your [IDOM](https://github.com/idom-team/idom) components. We recommend creating a `components.py` file within your chosen **Django app** to start out. |
122 | 31 |
|
123 | | -# Ensure DJANGO_SETTINGS_MODULE is set properly based on your project name! |
124 | | -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_project.settings") |
125 | | -django_asgi_app = get_asgi_application() |
| 32 | +<!--py-header-end--> |
| 33 | +<!--py-code-start--> |
126 | 34 |
|
127 | | -from channels.auth import AuthMiddlewareStack |
128 | | -from channels.routing import ProtocolTypeRouter, URLRouter |
129 | | -from channels.sessions import SessionMiddlewareStack |
130 | | -from django_idom import IDOM_WEBSOCKET_PATH |
| 35 | +```python title="components.py" |
| 36 | +from idom import component, html |
131 | 37 |
|
132 | | -application = ProtocolTypeRouter( |
133 | | - { |
134 | | - "http": django_asgi_app, |
135 | | - "websocket": SessionMiddlewareStack( |
136 | | - AuthMiddlewareStack(URLRouter([IDOM_WEBSOCKET_PATH])) |
137 | | - ), |
138 | | - } |
139 | | -) |
| 38 | +@component |
| 39 | +def HelloWorld(recipient: str): |
| 40 | + return html.h1(f"Hello {recipient}!") |
140 | 41 | ``` |
141 | 42 |
|
142 | | -# Developer Guide |
| 43 | +<!--py-code-end--> |
143 | 44 |
|
144 | | -If you plan to make code changes to this repository, you'll need to install the |
145 | | -following dependencies first: |
| 45 | +## [`my_app/templates/my-template.html`](https://docs.djangoproject.com/en/dev/topics/templates/) |
146 | 46 |
|
147 | | -- [NPM](https://docs.npmjs.com/try-the-latest-stable-version-of-npm) for |
148 | | - installing and managing Javascript |
149 | | -- [ChromeDriver](https://chromedriver.chromium.org/downloads) for testing with |
150 | | - [Selenium](https://www.seleniumhq.org/) |
| 47 | +<!--html-header-start--> |
151 | 48 |
|
152 | | -Once done, you should clone this repository: |
| 49 | +In your **Django app**'s HTML located within your `templates` folder, you can now embed your IDOM component using the `component` template tag. Within this tag, you will need to type in your dotted path to the component function as the first argument. |
153 | 50 |
|
154 | | -```bash |
155 | | -git clone https://github.com/idom-team/django-idom.git |
156 | | -cd django-idom |
157 | | -``` |
158 | | - |
159 | | -Then, by running the command below you can: |
| 51 | +Additonally, you can pass in keyword arguments into your component function. For example, after reading the code below, pay attention to how the function definition for `HelloWorld` (_in the previous example_) accepts a `recipient` argument. |
160 | 52 |
|
161 | | -- Install an editable version of the Python code |
| 53 | +<!--html-header-end--> |
| 54 | +<!--html-code-start--> |
162 | 55 |
|
163 | | -- Download, build, and install Javascript dependencies |
164 | | - |
165 | | -```bash |
166 | | -pip install -e . -r requirements.txt |
| 56 | +```jinja title="my-template.html" |
| 57 | +{% load idom %} |
| 58 | +<!DOCTYPE html> |
| 59 | +<html> |
| 60 | + <body> |
| 61 | + {% component "example_project.my_app.components.HelloWorld" recipient="World" %} |
| 62 | + </body> |
| 63 | +</html> |
167 | 64 | ``` |
168 | 65 |
|
169 | | -Finally, to verify that everything is working properly, you'll want to run the test suite. |
| 66 | +<!--html-code-end--> |
170 | 67 |
|
171 | | -## Running The Tests |
| 68 | +--- |
172 | 69 |
|
173 | | -This repo uses [Nox](https://nox.thea.codes/en/stable/) to run scripts which can |
174 | | -be found in `noxfile.py`. For a full test of available scripts run `nox -l`. To run the full test suite simple execute: |
| 70 | +# Resources |
175 | 71 |
|
176 | | -``` |
177 | | -nox -s test |
178 | | -``` |
| 72 | +<!--resources-start--> |
179 | 73 |
|
180 | | -To run the tests using a headless browser: |
| 74 | +Follow the links below to find out more about this project. |
181 | 75 |
|
182 | | -``` |
183 | | -nox -s test -- --headless |
184 | | -``` |
| 76 | +- [Try it Now](https://mybinder.org/v2/gh/idom-team/idom-jupyter/main?urlpath=lab/tree/notebooks/introduction.ipynb) - Check out IDOM in a Jupyter Notebook. |
| 77 | +- [Documentation](https://idom-team.github.io/django-idom) - Learn how to install, run, and use IDOM. |
| 78 | +- [Community Forum](https://github.com/idom-team/idom/discussions) - Ask questions, share ideas, and show off projects. |
| 79 | +<!--resources-end--> |
0 commit comments