diff --git a/CHANGELOG.md b/CHANGELOG.md index 20a85b93..caf95b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,12 +28,14 @@ Using the following categories, list your changes in this order: ### Changed +- `view_to_component` now returns a `Callable`, instead of directly returning a `Component`. Check the docs for new usage info. - `use_mutation` and `use_query` will now log any query failures. ### Fixed - Allow `use_mutation` to have `refetch=None`, as the docs suggest is possible. - `use_query` will now prefetch all fields to prevent `SynchronousOnlyOperation` exceptions. +- `view_to_component`, `django_css`, and `django_js` type hints will now display like normal functions. ## [1.2.0] - 2022-09-19 diff --git a/docs/includes/examples.md b/docs/includes/examples.md index 3ed273fd..0edbf273 100644 --- a/docs/includes/examples.md +++ b/docs/includes/examples.md @@ -1,27 +1,3 @@ - - -```python linenums="1" -from django.http import HttpResponse - -def hello_world_view(request, *args, **kwargs): - return HttpResponse("Hello World!") -``` - - - - - -```python linenums="1" -from django.http import HttpResponse -from django.views import View - -class HelloWorldView(View): - def get(self, request, *args, **kwargs): - return HttpResponse("Hello World!") -``` - - - ```python linenums="1" diff --git a/docs/src/features/components.md b/docs/src/features/components.md index 5886fc23..aee6f60d 100644 --- a/docs/src/features/components.md +++ b/docs/src/features/components.md @@ -10,20 +10,20 @@ Convert any Django view into a IDOM component by usng this decorator. Compatible ```python linenums="1" from idom import component, html + from django.http import HttpResponse from django_idom.components import view_to_component - from .views import hello_world_view + + @view_to_component + def hello_world_view(request): + return HttpResponse("Hello World!") @component def my_component(): return html.div( - view_to_component(hello_world_view), + hello_world_view(), ) ``` -=== "views.py" - - {% include-markdown "../../includes/examples.md" start="" end="" %} - ??? example "See Interface" **Parameters** @@ -31,73 +31,128 @@ Convert any Django view into a IDOM component by usng this decorator. Compatible | Name | Type | Description | Default | | --- | --- | --- | --- | | view | `Callable | View` | The view function or class to convert. | N/A | - | compatibility | `bool` | If True, the component will be rendered in an iframe. When using compatibility mode `tranforms`, `strict_parsing`, and `request` arguments will be ignored. | `False` | - | transforms | `Iterable[Callable[[VdomDict], Any]]` | A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. | `tuple` | + | compatibility | `bool` | If True, the component will be rendered in an iframe. When using compatibility mode `tranforms`, `strict_parsing`, `request`, `args`, and `kwargs` arguments will be ignored. | `False` | + | transforms | `Sequence[Callable[[VdomDict], Any]]` | A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. | `tuple` | | strict_parsing | `bool` | If True, an exception will be generated if the HTML does not perfectly adhere to HTML5. | `True` | - | request | `HttpRequest | None` | Request object to provide to the view. | `None` | - | args | `Iterable` | The positional arguments to pass to the view. | `tuple` | - | kwargs | `Dict | None` | The keyword arguments to pass to the view. | `None` | **Returns** | Type | Description | | --- | --- | - | `Component` | An IDOM component. | - | `None` | No component render. | + | `_ViewComponentConstructor` | A function that takes `request: HttpRequest | None, *args: Any, **kwargs: Any` and returns an IDOM component. | + +??? warning "Existing limitations" + + There are currently several limitations of using `view_to_component` that may be resolved in a future version of `django_idom`. + + - Requires manual intervention to change request methods beyond `GET`. + - Does not currently load any HTML contained with a `
` tag + - Has no option to automatically intercept local anchor link (ex. `#!html `) click events + + _Please note these limitations do not exist when using `compatibility` mode._ ??? question "How do I use this for Class Based Views?" - You can simply pass your Class Based View directly into this function. + You can simply pass your Class Based View directly into `view_to_component`. === "components.py" ```python linenums="1" from idom import component, html + from django.http import HttpResponse + from django.views import View from django_idom.components import view_to_component - from .views import HelloWorldView + + @view_to_component + class HelloWorldView(View): + def get(self, request): + return HttpResponse("Hello World!") @component def my_component(): return html.div( - view_to_component(HelloWorldView), + HelloWorldView(), ) ``` - === "views.py" +??? question "How do I transform views from external libraries?" + + === "components.py" - {% include-markdown "../../includes/examples.md" start="" end="" %} + In order to convert external views, you can utilize `view_to_component` as a function, rather than a decorator. -??? question "How do I pass arguments into the view?" + ```python linenums="1" + from idom import component, html + from django.http import HttpResponse + from django_idom.components import view_to_component + from some_library.views import example_view - You can use the `args` and `kwargs` parameters to pass arguments to the view. + converted_view = view_to_component(example_view) + + @component + def my_component(): + return html.div( + converted_view(), + ) + ``` + +??? question "How do I provide `args` and `kwargs` to a view?" + + You can use the `args` and `kwargs` parameters to provide positional and keyworded arguments to a view. === "components.py" ```python linenums="1" from idom import component, html + from django.http import HttpResponse from django_idom.components import view_to_component - from .views import hello_world_view + + @view_to_component + def hello_world_view(request, arg1, arg2, key1=None, key2=None): + return HttpResponse(f"Hello World! {arg1} {arg2} {key1} {key2}") @component def my_component(): return html.div( - view_to_component( - hello_world_view, + hello_world_view( args=["value_1", "value_2"], - kwargs={"key_1": "value_1", "key_2": "value_2"}, + kwargs={"key1": "abc", "key2": "123"}, ), ) ``` - === "views.py" +??? question "How do I provide a custom `request` object to a view?" - {% include-markdown "../../includes/examples.md" start="" end="" %} + You can use the `request` parameter to provide the view a custom request object. + + === "components.py" + + ```python linenums="1" + from idom import component, html + from django.http import HttpResponse, HttpRequest + from django_idom.components import view_to_component + + example_request = HttpRequest() + example_request.method = "PUT" + + @view_to_component + def hello_world_view(request): + return HttpResponse(f"Hello World! {request.method}") + + @component + def my_component(): + return html.div( + hello_world_view( + request=example_request, + ), + ) + ``` ??? question "What is `compatibility` mode?" For views that rely on HTTP responses other than `GET` (such as `PUT`, `POST`, `PATCH`, etc), you should consider using compatibility mode to render your view within an iframe. - Any view can be rendered within compatibility mode. However, the `transforms`, `strict_parsing`, and `request` arguments do not apply to compatibility mode. + Any view can be rendered within compatibility mode. However, the `transforms`, `strict_parsing`, `request`, `args`, and `kwargs` arguments do not apply to compatibility mode. Please note that by default the iframe is unstyled, and thus won't look pretty until you add some CSS. @@ -105,20 +160,20 @@ Convert any Django view into a IDOM component by usng this decorator. Compatible ```python linenums="1" from idom import component, html + from django.http import HttpResponse from django_idom.components import view_to_component - from .views import hello_world_view + + @view_to_component(compatibility=True) + def hello_world_view(request): + return HttpResponse("Hello World!") @component def my_component(): return html.div( - view_to_component(hello_world_view, compatibility=True), + hello_world_view(), ) ``` - === "views.py" - - {% include-markdown "../../includes/examples.md" start="" end="" %} - ??? question "What is `strict_parsing`?" By default, an exception will be generated if your view's HTML does not perfectly adhere to HTML5. @@ -131,20 +186,20 @@ Convert any Django view into a IDOM component by usng this decorator. Compatible ```python linenums="1" from idom import component, html + from django.http import HttpResponse from django_idom.components import view_to_component - from .views import hello_world_view + + @view_to_component(strict_parsing=False) + def hello_world_view(request): + return HttpResponse("