Skip to content

Commit

Permalink
Support for non-serializable component parameters (#120)
Browse files Browse the repository at this point in the history
- Database backed component parameters
   - The `component` template tag now supports both positional and keyword arguments.
   - The `component` template tag now supports non-serializable arguments.
   - It is now mandatory to run `manage.py migrate` after installing IDOM
   - `IDOM_WS_MAX_RECONNECT_TIMEOUT` has been renamed to `IDOM_RECONNECT_MAX` and is now used as the default timeout for component parameters
- Bumped the minimum IDOM version to 0.43.0
   - `idom.backend.hooks` support.
   - `django_idom.types.IdomWebsocket` has been renamed to `Connection` and modified to fit the new schema
   - `view_to_component` utility will now automatically use `del_html_head_body_transform`
   - Set `IDOM_DEBUG_MODE` to `settings.py:DEBUG`
- The react client is now set to production rather than development
- Make a harmless utils public but undocumented
- Documentation for `django_query_postprocessor`
  • Loading branch information
Archmonger authored Feb 2, 2023
1 parent da5248e commit da083ac
Show file tree
Hide file tree
Showing 47 changed files with 1,245 additions and 852 deletions.
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,35 @@ Using the following categories, list your changes in this order:

## [Unreleased]

### Added

- The `idom` client will automatically configure itself to debug mode depending on `settings.py:DEBUG`.
- `use_connection` hook for returning the browser's active `Connection`

### Changed

- The `component` template tag now supports both positional and keyword arguments.
- The `component` template tag now supports non-serializable arguments.
- `IDOM_WS_MAX_RECONNECT_TIMEOUT` setting has been renamed to `IDOM_RECONNECT_MAX`.
- It is now mandatory to run `manage.py migrate` after installing IDOM.
- Bumped the minimum IDOM version to 0.43.0

### Removed

- `django_idom.hooks.use_websocket` has been removed. The similar replacement is `django_idom.hooks.use_connection`.
- `django_idom.types.IdomWebsocket` has been removed. The similar replacement is `django_idom.types.Connection`

### Fixed

- `view_to_component` will now retain any HTML that was defined in a `<head>` tag.
- React client is now set to `production` rather than `development`.
- `use_query` will now utilize `field.related_name` when postprocessing many-to-one relationships

### Security

- Fixed a potential method of component template tag argument spoofing.
- Exception information will no longer be displayed on the page, based on the value of `settings.py:DEBUG`.

## [2.2.1] - 2022-01-09

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def hello_world(recipient: str):

In your **Django app**'s HTML template, you can now embed your IDOM component using the `component` template tag. Within this tag, you will need to type in your dotted path to the component function as the first argument.

Additionally, you can pass in keyword arguments into your component function. For example, after reading the code below, pay attention to how the function definition for `hello_world` (_in the previous example_) accepts a `recipient` argument.
Additionally, you can pass in `args` and `kwargs` into your component function. For example, after reading the code below, pay attention to how the function definition for `hello_world` (_in the previous example_) accepts a `recipient` argument.

<!--html-header-end-->
<!--html-code-start-->
Expand Down
6 changes: 3 additions & 3 deletions docs/src/contribute/code.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ If you plan to make code changes to this repository, you will need to install th

Once done, you should clone this repository:

```bash
```bash linenums="0"
git clone https://github.com/idom-team/django-idom.git
cd django-idom
```
Expand All @@ -20,13 +20,13 @@ Then, by running the command below you can:
- Install an editable version of the Python code
- Download, build, and install Javascript dependencies

```bash
```bash linenums="0"
pip install -e . -r requirements.txt
```

Finally, to verify that everything is working properly, you can manually run the development webserver.

```bash
```bash linenums="0"
cd tests
python manage.py runserver
```
Expand Down
6 changes: 3 additions & 3 deletions docs/src/contribute/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ If you plan to make changes to this documentation, you will need to install the

Once done, you should clone this repository:

```bash
```bash linenums="0"
git clone https://github.com/idom-team/django-idom.git
cd django-idom
```
Expand All @@ -15,13 +15,13 @@ Then, by running the command below you can:
- Install an editable version of the documentation
- Self-host a test server for the documentation

```bash
```bash linenums="0"
pip install -r ./requirements/build-docs.txt --upgrade
```

Finally, to verify that everything is working properly, you can manually run the docs preview webserver.

```bash
```bash linenums="0"
mkdocs serve
```

Expand Down
6 changes: 3 additions & 3 deletions docs/src/contribute/running-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ If you plan to run tests, you will need to install the following dependencies fi

Once done, you should clone this repository:

```bash
```bash linenums="0"
git clone https://github.com/idom-team/django-idom.git
cd django-idom
pip install -r ./requirements/test-run.txt --upgrade
```

Then, by running the command below you can run the full test suite:

```
```bash linenums="0"
nox -s test
```

Or, if you want to run the tests in the foreground:

```
```bash linenums="0"
nox -s test -- --headed
```
3 changes: 3 additions & 0 deletions docs/src/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ idom
asgi
postfixed
postprocessing
serializable
postprocessor
preprocessor
3 changes: 1 addition & 2 deletions docs/src/features/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ Convert any Django view into a IDOM component by using this decorator. Compatibl

- Requires manual intervention to change request methods beyond `GET`.
- IDOM events cannot conveniently be attached to converted view HTML.
- Does not currently load any HTML contained with a `<head>` tag
- Has no option to automatically intercept local anchor link (such as `#!html <a href='example/'></a>`) click events
- Has no option to automatically intercept local anchor link (such as `#!html <a href='example/'></a>`) click events.

_Please note these limitations do not exist when using `compatibility` mode._

Expand Down
8 changes: 1 addition & 7 deletions docs/src/features/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,16 @@

## Auth Required

You can limit access to a component to users with a specific `auth_attribute` by using this decorator.
You can limit access to a component to users with a specific `auth_attribute` by using this decorator (with or without parentheses).

By default, this decorator checks if the user is logged in, and his/her account has not been deactivated.

This decorator is commonly used to selectively render a component only if a user [`is_staff`](https://docs.djangoproject.com/en/dev/ref/contrib/auth/#django.contrib.auth.models.User.is_staff) or [`is_superuser`](https://docs.djangoproject.com/en/dev/ref/contrib/auth/#django.contrib.auth.models.User.is_superuser).

This decorator can be used with or without parentheses.

=== "components.py"

```python
from django_idom.decorators import auth_required
from django_idom.hooks import use_websocket
from idom import component, html

@component
Expand Down Expand Up @@ -70,7 +67,6 @@ This decorator can be used with or without parentheses.

```python
from django_idom.decorators import auth_required
from django_idom.hooks import use_websocket
from idom import component, html

@component
Expand All @@ -87,7 +83,6 @@ This decorator can be used with or without parentheses.

```python
from django_idom.decorators import auth_required
from django_idom.hooks import use_websocket
from idom import component, html


Expand Down Expand Up @@ -120,7 +115,6 @@ This decorator can be used with or without parentheses.

```python
from django_idom.decorators import auth_required
from django_idom.hooks import use_websocket
from idom import component, html

@component
Expand Down
66 changes: 33 additions & 33 deletions docs/src/features/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,20 +399,22 @@ The function you provide into this hook will have no return value.

{% include-markdown "../../includes/orm.md" start="<!--orm-excp-start-->" end="<!--orm-excp-end-->" %}

## Use Websocket
## Use Origin

This is a shortcut that returns the Websocket's `origin`.

You can fetch the Django Channels [websocket](https://channels.readthedocs.io/en/stable/topics/consumers.html#asyncjsonwebsocketconsumer) at any time by using `use_websocket`.
You can expect this hook to provide strings such as `http://example.com`.

=== "components.py"

```python
from idom import component, html
from django_idom.hooks import use_websocket
from django_idom.hooks import use_origin

@component
def my_component():
my_websocket = use_websocket()
return html.div(my_websocket)
my_origin = use_origin()
return html.div(my_origin)
```

??? example "See Interface"
Expand All @@ -425,22 +427,22 @@ You can fetch the Django Channels [websocket](https://channels.readthedocs.io/en

| Type | Description |
| --- | --- |
| `IdomWebsocket` | The component's websocket. |
| `str | None` | A string containing the browser's current origin, obtained from websocket headers (if available). |

## Use Scope
## Use Connection

This is a shortcut that returns the Websocket's [`scope`](https://channels.readthedocs.io/en/stable/topics/consumers.html#scope).
You can fetch the Django Channels [websocket](https://channels.readthedocs.io/en/stable/topics/consumers.html#asyncjsonwebsocketconsumer) at any time by using `use_connection`.

=== "components.py"

```python
from idom import component, html
from django_idom.hooks import use_scope
from django_idom.hooks import use_connection

@component
def my_component():
my_scope = use_scope()
return html.div(my_scope)
my_connection = use_connection()
return html.div(my_connection)
```

??? example "See Interface"
Expand All @@ -453,24 +455,22 @@ This is a shortcut that returns the Websocket's [`scope`](https://channels.readt

| Type | Description |
| --- | --- |
| `dict[str, Any]` | The websocket's `scope`. |
| `Connection` | The component's websocket. |

## Use Location

This is a shortcut that returns the Websocket's `path`.
## Use Scope

You can expect this hook to provide strings such as `/idom/my_path`.
This is a shortcut that returns the Websocket's [`scope`](https://channels.readthedocs.io/en/stable/topics/consumers.html#scope).

=== "components.py"

```python
from idom import component, html
from django_idom.hooks import use_location
from django_idom.hooks import use_scope

@component
def my_component():
my_location = use_location()
return html.div(my_location)
my_scope = use_scope()
return html.div(my_scope)
```

??? example "See Interface"
Expand All @@ -483,30 +483,24 @@ You can expect this hook to provide strings such as `/idom/my_path`.

| Type | Description |
| --- | --- |
| `Location` | A object containing the current URL's `pathname` and `search` query. |
| `MutableMapping[str, Any]` | The websocket's `scope`. |

??? info "This hook's behavior will be changed in a future update"

This hook will be updated to return the browser's currently active path. This change will come in alongside IDOM URL routing support.

Check out [idom-team/idom-router#2](https://github.com/idom-team/idom-router/issues/2) for more information.

## Use Origin
## Use Location

This is a shortcut that returns the Websocket's `origin`.
This is a shortcut that returns the Websocket's `path`.

You can expect this hook to provide strings such as `http://example.com`.
You can expect this hook to provide strings such as `/idom/my_path`.

=== "components.py"

```python
from idom import component, html
from django_idom.hooks import use_origin
from django_idom.hooks import use_location

@component
def my_component():
my_origin = use_origin()
return html.div(my_origin)
my_location = use_location()
return html.div(my_location)
```

??? example "See Interface"
Expand All @@ -519,4 +513,10 @@ You can expect this hook to provide strings such as `http://example.com`.

| Type | Description |
| --- | --- |
| `str | None` | A string containing the browser's current origin, obtained from websocket headers (if available). |
| `Location` | A object containing the current URL's `pathname` and `search` query. |

??? info "This hook's behavior will be changed in a future update"

This hook will be updated to return the browser's currently active path. This change will come in alongside IDOM URL routing support.

Check out [idom-team/idom-router#2](https://github.com/idom-team/idom-router/issues/2) for more information.
11 changes: 6 additions & 5 deletions docs/src/features/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
<!--settings-start-->

```python
# If "idom" cache is not configured, then we will use "default" instead
# If "idom" cache is not configured, then "default" will be used
# IDOM expects a multiprocessing-safe and thread-safe cache backend.
CACHES = {
"idom": {"BACKEND": ...},
}

# Maximum seconds between two reconnection attempts that would cause the client give up.
# 0 will disable reconnection.
IDOM_WS_MAX_RECONNECT_TIMEOUT = 604800
# Maximum seconds between reconnection attempts before giving up.
# Use `0` to prevent component reconnection.
IDOM_RECONNECT_MAX = 259200

# The URL for IDOM to serve websockets
# The URL for IDOM to serve the component rendering websocket
IDOM_WEBSOCKET_URL = "idom/"

# Dotted path to the default postprocessor function, or `None`
Expand Down
Loading

0 comments on commit da083ac

Please sign in to comment.