Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
30a481f
create barebones templatetags
Archmonger Jul 22, 2021
8b0b363
styling fix
Archmonger Jul 22, 2021
4bcd9bf
idom_view
Archmonger Jul 26, 2021
f8f094e
skeleton of django installable app
rmorshea Jul 26, 2021
937da20
get test_app runserver to work
rmorshea Jul 26, 2021
e76408b
fix MANIFEST.in to include static/templates
rmorshea Jul 28, 2021
f008f6b
fix style
rmorshea Jul 28, 2021
b4f256b
require a my_app.idom.components attribute
rmorshea Jul 28, 2021
a0b75e0
parametrized components + serve web modules
rmorshea Jul 28, 2021
cd12a7c
add IDOM_IGNORED_DJANGO_APPS option
rmorshea Jul 29, 2021
9f4412d
add basic docs to README
rmorshea Jul 29, 2021
34452e4
minor doc improvements
rmorshea Jul 29, 2021
3e07d5a
more doc updates
rmorshea Jul 29, 2021
0ff84ec
make logger private
rmorshea Aug 5, 2021
fbb0037
use string path to template
rmorshea Aug 5, 2021
407b506
rename URL resolver functions
rmorshea Aug 5, 2021
fa95bb1
fix flake8
rmorshea Aug 5, 2021
9da3de8
correct template tag description
rmorshea Aug 5, 2021
a05d0ef
update app organization in README
rmorshea Aug 5, 2021
937244c
switch to decorator collection method
rmorshea Aug 11, 2021
af6601d
load components using template names
rmorshea Aug 12, 2021
60384af
minor README tweaks
rmorshea Aug 12, 2021
f72b2d6
remove unused config option
rmorshea Aug 12, 2021
4bcdeb5
use different param name in README ex
rmorshea Aug 12, 2021
536968a
cache and asyncify web module loading
rmorshea Aug 19, 2021
aee70a7
rename idom_view to idom_component
rmorshea Aug 19, 2021
7093252
README rename your_template to your_view
rmorshea Aug 19, 2021
66b7cb3
fix README typo
rmorshea Aug 19, 2021
4a4fa74
make websocket and web module paths consts
rmorshea Aug 19, 2021
b209995
correct terminology
rmorshea Aug 19, 2021
b9934de
slim down README asgi.py description
rmorshea Aug 19, 2021
fa70766
better summarize what IDOM is
rmorshea Aug 19, 2021
a15c334
bump copyright year
rmorshea Aug 19, 2021
aed7fc7
fix template formatting
rmorshea Aug 19, 2021
68aa643
rename your_app to your_project
rmorshea Aug 19, 2021
83e3f7c
add CODEOWNERS
rmorshea Aug 19, 2021
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update app organization in README
  • Loading branch information
rmorshea committed Aug 5, 2021
commit a05d0efcb3ab0ba2bfdfd581afc7bd75f9af93f2
115 changes: 78 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,17 @@ To integrate IDOM into your application you'll need to modify or add the followi

```
your_app/
├── __init__.py
├── asgi.py
├── components.py
├── idom.py
├── settings.py
├── templates/
│ ├── your-template.html
└── urls.py
├── urls.py
└── sub_app/
├── __init__.py
├── components.py
├── idom.py
├── templates/
│ └── your-template.html
└── urls.py
```

## `asgi.py`
Expand All @@ -54,7 +58,7 @@ To start, we'll need to use [`channels`](https://channels.readthedocs.io/en/stab
create a `ProtocolTypeRouter` that will become the top of our ASGI application stack.
Under the `"websocket"` protocol, we'll then add a path for IDOM's websocket consumer
using `idom_websocket_path`. If you wish to change the route where this
websocket is served from see the [settings](#configuration-options).
websocket is served from see the available [settings](#settings.py).

```python

Expand Down Expand Up @@ -82,7 +86,44 @@ application = ProtocolTypeRouter(
)
```

## `components.py`
## `settings.py`

In your settings you'll need to add `django_idom` to the
[`INSTALLED_APPS`](https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-INSTALLED_APPS)
list:

```python
INSTALLED_APPS = [
...,
"django_idom",
]
```

You may configure additional options as well:

```python
# the base URL for all IDOM-releated resources
IDOM_BASE_URL: str = "_idom/"

# ignore these INSTALLED_APPS during component collection
IDOM_IGNORE_INSTALLED_APPS: list[str] = ["some_app", "some_other_app"]
```

## `urls.py`

You'll need to include IDOM's static web modules path using `idom_web_modules_path`.
Similarly to the `idom_websocket_path()`, these resources will be used globally.

```python
from django_idom import idom_web_modules_path

urlpatterns = [
idom_web_modules_path(),
...
]
```

## `sub_app/components.py`

This is where, by a convention similar to that of
[`views.py`](https://docs.djangoproject.com/en/3.2/topics/http/views/), you'll define
Expand All @@ -97,35 +138,36 @@ def Hello(name): # component names are camelcase by convention
return idom.html.h1(f"Hello {name}!")
```

## `idom.py`
## `sub_app/idom.py`

This file is automatically discovered by `django-idom` when scanning the list of
[`INSTALLED_APPS`](https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-INSTALLED_APPS).
All apps that export components will contain this module.

Inside this module must be a `components` list that is imported from
[`components.py`](#components.py):
[`components.py`](#sub_appcomponents.py):

```python
from .components import Hello

components = [Hello]
components = [
Hello,
...
]
```

## `settings.py`

In your settings you'll need to add `django_idom` to the
[`INSTALLED_APPS`](https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-INSTALLED_APPS)
list:
You may alternately reference the components with strings for the purpose of renaming:

```python
INSTALLED_APPS = [
...,
"django_idom",
from .components import Hello as SomeOtherName

components = [
"SomeOtherName",
...
]
```

## `templates/your-template.html`
## `sub_app/templates/your-template.html`

In your templates, you may inject a view of an IDOM component into your templated HTML
by using the `idom_view` template tag. This tag which requires the name of a component
Expand All @@ -147,41 +189,40 @@ In context this will look a bit like the following...
<html>
<body>
...
{% idom_view "test_app.Hello" name="World" %}
{% idom_view "your_app.sub_app.Hello" name="World" %}
</body>
</html>
```

Your view for this template can be defined just
[like any other](https://docs.djangoproject.com/en/3.2/intro/tutorial03/#write-views-that-actually-do-something).

## `urls.py`

To your list of URLs you'll need to include IDOM's static web modules path using
`idom_web_modules_path`:
## `sub_app/views.py`

```python
from django.urls import path
from django_idom import idom_web_modules_path
from .views import your_template # define this view like any other HTML template
from django.http import HttpResponse
from django.template import loader


urlpatterns = [
path("", your_template),
idom_web_modules_path(),
]
def your_template(request):
context = {}
return HttpResponse(
loader.get_template("your-template.html").render(context, request)
)
```

# Configuration Options
## `sub_app/urls.py`

You may configure additional options in your `settings.py` file
Include your replate in the list of urlpatterns

```python
# the base URL for all IDOM-releated resources
IDOM_BASE_URL: str = "_idom/"
from django.urls import path
from .views import your_template # define this view like any other HTML template

# ignore these INSTALLED_APPS during component collection
IDOM_IGNORE_INSTALLED_APPS: set[str] = {"some_app", "some_other_app"}
urlpatterns = [
path("", your_template),
...
]
```

# Developer Guide
Expand Down
22 changes: 14 additions & 8 deletions src/django_idom/app_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,25 @@ def has_component(name: str) -> bool:
)
continue

for component_constructor in idom_mod.components:
for component_value in idom_mod.components:
if isinstance(component_value, str):
component_name = component_value
component_constructor = getattr(idom_mod, component_name)
else:
component_constructor = component_value

try:
component_name = getattr(component_constructor, "__name__")
except AttributeError:
raise ValueError(
f"Component constructor {component_constructor} has no attribute '__name__'"
)

if not callable(component_constructor):
raise ValueError(
f"{component_constructor} is not a callable component constructor"
)

try:
component_name = getattr(component_constructor, "__name__")
except AttributeError:
raise ValueError(
f"Component constructor {component_constructor} has not attribute '__name__'"
)

full_component_name = f"{app_mod_name}.{component_name}"

if full_component_name in _LOADED_COMPONENTS:
Expand Down
3 changes: 1 addition & 2 deletions tests/test_app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@


def base_template(request):
template = loader.get_template("base.html")
context = {}
return HttpResponse(template.render(context, request))
return HttpResponse(loader.get_template("base.html").render(context, request))