mirror of
https://github.com/django-components/django-components.git
synced 2025-08-11 01:38:00 +00:00
refactor: compat with comp as view by reusing comp instance
This commit is contained in:
parent
7c52acf411
commit
36cd6e3f06
2 changed files with 53 additions and 1 deletions
|
@ -228,6 +228,20 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
||||||
self.component_id = component_id or gen_id()
|
self.component_id = component_id or gen_id()
|
||||||
self._context: Optional[Context] = None
|
self._context: Optional[Context] = None
|
||||||
|
|
||||||
|
# When user first instantiates the component class before calling
|
||||||
|
# `render` or `render_to_response`, then we want to allow the render
|
||||||
|
# function to make use of the instantiated object.
|
||||||
|
#
|
||||||
|
# So while `MyComp.render()` creates a new instance of MyComp internally,
|
||||||
|
# if we do `MyComp(registered_name="abc").render()`, then we use the
|
||||||
|
# already-instantiated object.
|
||||||
|
#
|
||||||
|
# To achieve that, we want to re-assign the class methods as instance methods.
|
||||||
|
# For that we have to "unwrap" the class methods via __func__.
|
||||||
|
# See https://stackoverflow.com/a/76706399/9788634
|
||||||
|
self.render_to_response = types.MethodType(self.__class__.render_to_response.__func__, self) # type: ignore
|
||||||
|
self.render = types.MethodType(self.__class__.render.__func__, self) # type: ignore
|
||||||
|
|
||||||
def __init_subclass__(cls, **kwargs: Any) -> None:
|
def __init_subclass__(cls, **kwargs: Any) -> None:
|
||||||
cls._class_hash = hash(inspect.getfile(cls) + cls.__name__)
|
cls._class_hash = hash(inspect.getfile(cls) + cls.__name__)
|
||||||
|
|
||||||
|
@ -440,7 +454,13 @@ class Component(View, metaclass=SimplifiedInterfaceMediaDefiningClass):
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
comp = cls()
|
# This method may be called as class method or as instance method.
|
||||||
|
# If called as class method, create a new instance.
|
||||||
|
if isinstance(cls, Component):
|
||||||
|
comp: Component = cls
|
||||||
|
else:
|
||||||
|
comp = cls()
|
||||||
|
|
||||||
return comp._render(context, args, kwargs, slots, escape_slots_content)
|
return comp._render(context, args, kwargs, slots, escape_slots_content)
|
||||||
|
|
||||||
def _render(
|
def _render(
|
||||||
|
|
|
@ -477,3 +477,35 @@ class ComponentRenderTest(BaseTestCase):
|
||||||
|
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@parametrize_context_behavior(["django", "isolated"])
|
||||||
|
def test_render_can_access_instance(self):
|
||||||
|
class TestComponent(component.Component):
|
||||||
|
template = "Variable: <strong>{{ id }}</strong>"
|
||||||
|
|
||||||
|
def get_context_data(self, **attrs):
|
||||||
|
return {
|
||||||
|
"id": self.component_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
rendered = TestComponent(component_id="123").render()
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
rendered,
|
||||||
|
"Variable: <strong>123</strong>",
|
||||||
|
)
|
||||||
|
|
||||||
|
@parametrize_context_behavior(["django", "isolated"])
|
||||||
|
def test_render_to_response_can_access_instance(self):
|
||||||
|
class TestComponent(component.Component):
|
||||||
|
template = "Variable: <strong>{{ id }}</strong>"
|
||||||
|
|
||||||
|
def get_context_data(self, **attrs):
|
||||||
|
return {
|
||||||
|
"id": self.component_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
rendered_resp = TestComponent(component_id="123").render_to_response()
|
||||||
|
self.assertHTMLEqual(
|
||||||
|
rendered_resp.content.decode('utf-8'),
|
||||||
|
"Variable: <strong>123</strong>",
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue