Skip to content

Commit a05d0ef

Browse files
committed
update app organization in README
1 parent 9da3de8 commit a05d0ef

File tree

3 files changed

+93
-47
lines changed

3 files changed

+93
-47
lines changed

README.md

+78-37
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,17 @@ To integrate IDOM into your application you'll need to modify or add the followi
3939

4040
```
4141
your_app/
42+
├── __init__.py
4243
├── asgi.py
43-
├── components.py
44-
├── idom.py
4544
├── settings.py
46-
├── templates/
47-
│ ├── your-template.html
48-
└── urls.py
45+
├── urls.py
46+
└── sub_app/
47+
├── __init__.py
48+
├── components.py
49+
├── idom.py
50+
├── templates/
51+
│ └── your-template.html
52+
└── urls.py
4953
```
5054

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

5963
```python
6064

@@ -82,7 +86,44 @@ application = ProtocolTypeRouter(
8286
)
8387
```
8488

85-
## `components.py`
89+
## `settings.py`
90+
91+
In your settings you'll need to add `django_idom` to the
92+
[`INSTALLED_APPS`](https://docs.djangoproject.com/en/3.2/ref/settings/#std:setting-INSTALLED_APPS)
93+
list:
94+
95+
```python
96+
INSTALLED_APPS = [
97+
...,
98+
"django_idom",
99+
]
100+
```
101+
102+
You may configure additional options as well:
103+
104+
```python
105+
# the base URL for all IDOM-releated resources
106+
IDOM_BASE_URL: str = "_idom/"
107+
108+
# ignore these INSTALLED_APPS during component collection
109+
IDOM_IGNORE_INSTALLED_APPS: list[str] = ["some_app", "some_other_app"]
110+
```
111+
112+
## `urls.py`
113+
114+
You'll need to include IDOM's static web modules path using `idom_web_modules_path`.
115+
Similarly to the `idom_websocket_path()`, these resources will be used globally.
116+
117+
```python
118+
from django_idom import idom_web_modules_path
119+
120+
urlpatterns = [
121+
idom_web_modules_path(),
122+
...
123+
]
124+
```
125+
126+
## `sub_app/components.py`
86127

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

100-
## `idom.py`
141+
## `sub_app/idom.py`
101142

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

106147
Inside this module must be a `components` list that is imported from
107-
[`components.py`](#components.py):
148+
[`components.py`](#sub_appcomponents.py):
108149

109150
```python
110151
from .components import Hello
111152

112-
components = [Hello]
153+
components = [
154+
Hello,
155+
...
156+
]
113157
```
114158

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

121161
```python
122-
INSTALLED_APPS = [
123-
...,
124-
"django_idom",
162+
from .components import Hello as SomeOtherName
163+
164+
components = [
165+
"SomeOtherName",
166+
...
125167
]
126168
```
127169

128-
## `templates/your-template.html`
170+
## `sub_app/templates/your-template.html`
129171

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

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

158-
## `urls.py`
159-
160-
To your list of URLs you'll need to include IDOM's static web modules path using
161-
`idom_web_modules_path`:
200+
## `sub_app/views.py`
162201

163202
```python
164-
from django.urls import path
165-
from django_idom import idom_web_modules_path
166-
from .views import your_template # define this view like any other HTML template
203+
from django.http import HttpResponse
204+
from django.template import loader
167205

168206

169-
urlpatterns = [
170-
path("", your_template),
171-
idom_web_modules_path(),
172-
]
207+
def your_template(request):
208+
context = {}
209+
return HttpResponse(
210+
loader.get_template("your-template.html").render(context, request)
211+
)
173212
```
174213

175-
# Configuration Options
214+
## `sub_app/urls.py`
176215

177-
You may configure additional options in your `settings.py` file
216+
Include your replate in the list of urlpatterns
178217

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

183-
# ignore these INSTALLED_APPS during component collection
184-
IDOM_IGNORE_INSTALLED_APPS: set[str] = {"some_app", "some_other_app"}
222+
urlpatterns = [
223+
path("", your_template),
224+
...
225+
]
185226
```
186227

187228
# Developer Guide

src/django_idom/app_components.py

+14-8
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,25 @@ def has_component(name: str) -> bool:
4040
)
4141
continue
4242

43-
for component_constructor in idom_mod.components:
43+
for component_value in idom_mod.components:
44+
if isinstance(component_value, str):
45+
component_name = component_value
46+
component_constructor = getattr(idom_mod, component_name)
47+
else:
48+
component_constructor = component_value
49+
50+
try:
51+
component_name = getattr(component_constructor, "__name__")
52+
except AttributeError:
53+
raise ValueError(
54+
f"Component constructor {component_constructor} has no attribute '__name__'"
55+
)
56+
4457
if not callable(component_constructor):
4558
raise ValueError(
4659
f"{component_constructor} is not a callable component constructor"
4760
)
4861

49-
try:
50-
component_name = getattr(component_constructor, "__name__")
51-
except AttributeError:
52-
raise ValueError(
53-
f"Component constructor {component_constructor} has not attribute '__name__'"
54-
)
55-
5662
full_component_name = f"{app_mod_name}.{component_name}"
5763

5864
if full_component_name in _LOADED_COMPONENTS:

tests/test_app/views.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33

44

55
def base_template(request):
6-
template = loader.get_template("base.html")
76
context = {}
8-
return HttpResponse(template.render(context, request))
7+
return HttpResponse(loader.get_template("base.html").render(context, request))

0 commit comments

Comments
 (0)