Skip to content

Commit 3b8edf1

Browse files
committed
Improve the createlivecomponent management command
Fix the Python template and add a --stateless option to create a stateless component.
1 parent b05dd68 commit 3b8edf1

File tree

4 files changed

+56
-6
lines changed

4 files changed

+56
-6
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## UNRELEASED
9+
10+
- Improved the createlivecomponent management command: fixed the Python template and added a --stateless option to create a stateless component.
11+
812
## 1.12.4 (2024-08-15)
913

1014
- Improved serialization for Django forms and models: pickle now correctly handles unsaved Django model instances and validates bound forms during unpickling.

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ of one Python, and one HTML file.
140140

141141
Make sure that your STATICFILES_DIRS setting includes the "components" directory of the app.
142142

143+
Optionally, you can pass a `--stateless` flag to create a stateless component.
144+
143145

144146
## On Component IDs
145147

livecomponents/management/commands/_templates.py

+33-5
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,38 @@ def get_extra_context_data(
3636
return {{}}
3737
3838
def init_state(self, context: InitStateContext) -> {class_name}State:
39-
return {class_name}State(**component_kwargs)
39+
return {class_name}State(**context.component_kwargs)
4040
41-
# @command
42-
# def say_hello(self, call_context: CallContext[{class_name}State]):
43-
# \"\"\"Example command.\"\"\"
44-
# pass
41+
@command
42+
def say_hello(self, call_context: CallContext[{class_name}State]):
43+
\"\"\"Example command.\"\"\"
44+
pass
45+
"""
46+
47+
STATELESS_COMPONENT_PYTHON_TEMPLATE = """from typing import Any
48+
from typing import Any
49+
from django_components import component
50+
51+
from livecomponents import (
52+
ExtraContextRequest,
53+
StatelessLiveComponent,
54+
command,
55+
CallContext,
56+
)
57+
58+
@component.register("{component_name}")
59+
class {class_name}Component(StatelessLiveComponent):
60+
template_name = "{component_name}/{proper_name}.html"
61+
62+
63+
def get_extra_context_data(
64+
self, extra_context_request: ExtraContextRequest
65+
) -> dict[str, Any]:
66+
\"\"\"Return extra context to render the component template.\"\"\"
67+
return {{}}
68+
69+
@command
70+
def say_hello(self, call_context: CallContext):
71+
\"\"\"Example command.\"\"\"
72+
pass
4573
"""

livecomponents/management/commands/createlivecomponent.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from livecomponents.management.commands._templates import (
77
COMPONENT_HTML_TEMPLATE,
88
COMPONENT_PYTHON_TEMPLATE,
9+
STATELESS_COMPONENT_PYTHON_TEMPLATE,
910
)
1011

1112

@@ -40,10 +41,16 @@ def add_arguments(self, parser):
4041
action="store_true",
4142
help="Overwrite existing files",
4243
)
44+
parser.add_argument(
45+
"--stateless",
46+
action="store_true",
47+
help="Create a stateless component",
48+
)
4349

4450
def handle(self, *args, **options):
4551
app_name = options["app_name"]
4652
component_name = options["component_name"]
53+
stateless = options["stateless"]
4754
proper_name = component_name.split("/")[-1]
4855

4956
class_name = options["class_name"]
@@ -83,7 +90,7 @@ def handle(self, *args, **options):
8390
"proper_name": proper_name,
8491
"class_name": class_name,
8592
}
86-
component_py.write_text(COMPONENT_PYTHON_TEMPLATE.format(**context))
93+
component_py.write_text(self.get_python_template(stateless).format(**context))
8794
component_html.write_text(COMPONENT_HTML_TEMPLATE.format(**context))
8895
self.stdout.write(
8996
self.style.SUCCESS(
@@ -97,6 +104,15 @@ def handle(self, *args, **options):
97104
self.stdout.write(
98105
f'- Use component as {{% livecomponent "{component_name}" %}}'
99106
)
107+
self.stdout.write(
108+
f"- If the component is called from a parent component, use it as "
109+
f'{{% livecomponent "{component_name}" parent_id=component_id %}}'
110+
)
111+
112+
def get_python_template(self, stateless: bool) -> str:
113+
if stateless:
114+
return STATELESS_COMPONENT_PYTHON_TEMPLATE
115+
return COMPONENT_PYTHON_TEMPLATE
100116

101117
def get_app_path(self, app_name: str) -> Path:
102118
for app_config in apps.get_app_configs():

0 commit comments

Comments
 (0)