refactor: pass instantiated component to as_view (#664)

This commit is contained in:
Juro Oravec 2024-09-11 21:55:11 +02:00 committed by GitHub
parent 313afee1d9
commit 239923b221
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 2 deletions

View file

@ -85,6 +85,7 @@ And this is what gets rendered (plus the CSS and Javascript you've specified):
- [See here how to migrate your settings.py](https://github.com/EmilStenstrom/django-components/blob/master/docs/migrating_from_safer_staticfiles.md)
- Beside the top-level `/components` directory, you can now define also app-level components dirs, e.g. `[app]/components`
(See [`COMPONENTS.app_dirs`](#app_dirs)).
- When you call `as_view()` on a component instance, that instance will be passed to `View.as_view()`
**Version 0.97**
- Fixed template caching. You can now also manually create cached templates with [`cached_template()`](#template_cache_size---tune-the-template-cache)

View file

@ -252,6 +252,7 @@ class Component(Generic[ArgsType, KwargsType, DataType, SlotsType], metaclass=Co
# 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
self.as_view = types.MethodType(self.__class__.as_view.__func__, self) # type: ignore
self.registered_name: Optional[str] = registered_name
self.outer_context: Context = outer_context or Context()
@ -439,9 +440,15 @@ class Component(Generic[ArgsType, KwargsType, DataType, SlotsType], metaclass=Co
"""
Shortcut for calling `Component.View.as_view` and passing component instance to it.
"""
# 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()
# Allow the View class to access this component via `self.component`
component = cls()
return component.View.as_view(**initkwargs, component=component)
return comp.View.as_view(**initkwargs, component=comp)
@classmethod
def render_to_response(

View file

@ -160,6 +160,28 @@ class TestComponentAsView(BaseTestCase):
response.content,
)
def test_instantiate_component(self):
class MockComponentRequest(Component):
template = """
<form method="post">
<input type="text" name="variable" value="{{ inner_var }}">
</form>
"""
def get_context_data(self, variable):
return {"inner_var": variable}
def get(self, request, *args, **kwargs) -> HttpResponse:
return self.render_to_response(kwargs={"variable": self.name})
client = CustomClient(urlpatterns=[path("test/", MockComponentRequest("my_comp").as_view())])
response = client.get("/test/")
self.assertEqual(response.status_code, 200)
self.assertIn(
b'<input type="text" name="variable" value="my_comp">',
response.content,
)
@parametrize_context_behavior(["django", "isolated"])
def test_replace_slot_in_view(self):
class MockComponentSlot(Component):