Skip to content

use_query and use_mutation #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 60 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
c01152a
wip use_query and use_mutation
rmorshea Jul 2, 2022
86b6575
fetch deferred attrs
rmorshea Jul 15, 2022
780251c
update comment
rmorshea Jul 15, 2022
e465055
use dataclass instead of namedtuple
rmorshea Jul 15, 2022
adc69b6
sort imports
rmorshea Jul 15, 2022
84f8332
move undefined to types module
Archmonger Jul 26, 2022
e618868
formatting
Archmonger Jul 26, 2022
2d8d9e9
attempt fix for checkout warning
Archmonger Jul 26, 2022
70e3c91
fix docs typo
Archmonger Jul 26, 2022
f3b1d9e
add to changelog
Archmonger Jul 26, 2022
f920ae6
change event function name
Archmonger Jul 26, 2022
2c2e4e1
separate query/mutation docs
Archmonger Jul 26, 2022
725995b
enable link checking
Archmonger Jul 26, 2022
196c7ba
verbose link checking
Archmonger Jul 26, 2022
6180719
bump setup python version
Archmonger Jul 26, 2022
ae7c754
bump setup node
Archmonger Jul 26, 2022
b1b1552
fix task name
Archmonger Jul 26, 2022
01c427f
Update src/django_idom/hooks.py
Archmonger Jul 26, 2022
5c81104
Merge branch 'use_database' of https://github.com/idom-team/django-id…
Archmonger Jul 26, 2022
da9f4ce
Can `use_mutation` trigger refetch of a `use_query`
Archmonger Jul 26, 2022
08950d9
wordsmith
Archmonger Jul 26, 2022
d67f9b4
event["target"]["value"]
Archmonger Jul 29, 2022
6cb01fa
Ignore some type hints
Archmonger Jul 30, 2022
1317701
add ORM clarification
Archmonger Jul 30, 2022
308b5d1
misc fixes + remove fetch_deferred_fields
rmorshea Jul 30, 2022
7327106
remove unused code
Archmonger Jul 30, 2022
668ffc3
More typehint cleanup
Archmonger Jul 30, 2022
4c3de35
put deferred fetch back
rmorshea Aug 2, 2022
8f73020
switch from selenium to playwright
rmorshea Aug 2, 2022
7b6ced3
add basic test
rmorshea Aug 2, 2022
0b5c1fd
fix style
rmorshea Aug 2, 2022
02936e3
headless by default
rmorshea Aug 2, 2022
f437106
increase DB timeout
Archmonger Aug 2, 2022
acfe4e5
add todo item to admin site
Archmonger Aug 2, 2022
aa6139a
fix item done toggle
Archmonger Aug 2, 2022
e56255e
format
Archmonger Aug 2, 2022
8595c4e
attempt using onChange as devtools suggests
Archmonger Aug 2, 2022
a007566
remove accidental sleep
Archmonger Aug 2, 2022
093fc36
try to fix tests
rmorshea Aug 9, 2022
83b2d01
fix setup.py for deprecated distutils
rmorshea Aug 14, 2022
6a754cf
use propper skip error
rmorshea Aug 14, 2022
3d336b3
bump idom dep
rmorshea Aug 14, 2022
38de554
Fix context type hint
Archmonger Aug 14, 2022
5203f0d
bump idom
Archmonger Sep 12, 2022
1f2ed01
remove unused import
rmorshea Sep 13, 2022
ab07327
Merge branch 'main' into use_database
rmorshea Sep 13, 2022
0b8013c
no mypy on tests
rmorshea Sep 13, 2022
fd09362
bump idom-client-react
Archmonger Sep 13, 2022
1e1d979
bump idom version
rmorshea Sep 13, 2022
a53ece4
add delay to typing
rmorshea Sep 13, 2022
ca289d0
revert idom.html changes in tests
Archmonger Sep 14, 2022
281c5af
clean up noxfile
Archmonger Sep 14, 2022
949e815
bump idom client
Archmonger Sep 14, 2022
80b1471
Merge branch 'use_database' of https://github.com/idom-team/django-id…
Archmonger Sep 14, 2022
ba42a8b
Move mutation and query to types.py
Archmonger Sep 14, 2022
b174a80
Python < 3.10 compatibility
Archmonger Sep 14, 2022
0324b06
Revert "Python < 3.10 compatibility"
Archmonger Sep 14, 2022
19806cb
from __future__ import annotations
Archmonger Sep 14, 2022
f672798
remove TransactionTestCase
Archmonger Sep 15, 2022
81928fb
revert channels login changes
Archmonger Sep 15, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/publish-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: 3.x
- run: pip install -r requirements/build-docs.txt
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/publish-py.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ jobs:
release-package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2-beta
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "14.x"
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: "3.x"
- name: Install latest NPM
- name: Install NPM
run: |
npm install -g [email protected]
npm --version
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/test-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-python@v4
with:
python-version: 3.x
- run: pip install -r requirements/build-docs.txt
- run: linkcheckMarkdown docs/ -v -r
- run: mkdocs build --verbose
8 changes: 4 additions & 4 deletions .github/workflows/test-src.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ jobs:
matrix:
python-version: ["3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: nanasess/setup-chromedriver@master
- uses: actions/setup-node@v2-beta
- uses: actions/setup-node@v3
with:
node-version: "14"
- name: Use Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install Python Dependencies
Expand All @@ -32,4 +32,4 @@ jobs:
run: |
npm install -g npm@latest
npm --version
nox -s test -- --headless
nox -s test
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Using the following categories, list your changes in this order:
### Added

- `auth_required` decorator to prevent your components from rendered to unauthenticated users.
- `use_query` hook for fetching database values.
- `use_mutation` hook for modifying database values.

## [1.1.0] - 2022-07-01

Expand Down
1 change: 0 additions & 1 deletion docs/features/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def my_component():

```python title="components.py"
from django_idom.decorators import auth_required
from django_idom.hooks import use_websocket
from idom import component, html

@component
Expand Down
157 changes: 157 additions & 0 deletions docs/features/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,163 @@

Check out the [IDOM Core docs](https://idom-docs.herokuapp.com/docs/reference/hooks-api.html?highlight=hooks) on hooks!

## Use Query

The `use_query` hook is used fetch Django ORM queries.

=== "components.py"

```python
from example_project.my_app.models import TodoItem
from idom import component, html
from django_idom.hooks import use_query

def get_items():
return TodoItem.objects.all()

@component
def todo_list():
item_query = use_query(get_items)

if item_query.loading:
rendered_items = html.h2("Loading...")
elif item_query.error:
rendered_items = html.h2("Error when loading!")
else:
rendered_items = html.ul(html.li(item, key=item) for item in item_query.data)

return rendered_items
```

=== "models.py"

```python
from django.db import models

class TodoItem(models.Model):
text = models.CharField(max_length=255)
```

??? question "Can I make ORM calls without hooks?"

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a `SynchronousOnlyOperation` exception.

This may be resolved in a future version of Django with a natively asynchronous ORM.

??? question "What is an "ORM"?"

A Python **Object Relational Mapper** is an API for your code to access a database.

See the [Django ORM documentation](https://docs.djangoproject.com/en/dev/topics/db/queries/) for more information.

## Use Mutation

The `use_mutation` hook is used to modify Django ORM objects.

=== "components.py"

```python
from example_project.my_app.models import TodoItem
from idom import component, html
from django_idom.hooks import use_mutation

def add_item(text: str):
TodoItem(text=text).save()

@component
def todo_list():
item_mutation = use_mutation(add_item)

if item_mutation.loading:
mutation_status = html.h2("Adding...")
elif item_mutation.error:
mutation_status = html.h2("Error when adding!")
else:
mutation_status = ""

def submit_event(event):
if event["key"] == "Enter":
item_mutation.execute(text=event["target"]["value"])

return html.div(
html.label("Add an item:"),
html.input({"type": "text", "onKeyDown": submit_event}),
mutation_status,
)
```

=== "models.py"

```python
from django.db import models

class TodoItem(models.Model):
text = models.CharField(max_length=255)
```

??? question "Can `use_mutation` trigger a refetch of `use_query`?"

Yes, `use_mutation` can queue a refetch of a `use_query` via the `refetch=...` argument.

The example below is a merge of the `use_query` and `use_mutation` examples above with the addition of a `refetch` argument on `use_mutation`.

Please note that any `use_query` hooks that use `get_items` will be refetched upon a successful mutation.

```python title="components.py"
from example_project.my_app.models import TodoItem
from idom import component, html
from django_idom.hooks import use_mutation

def get_items():
return TodoItem.objects.all()

def add_item(text: str):
TodoItem(text=text).save()

@component
def todo_list():
item_query = use_query(get_items)
if item_query.loading:
rendered_items = html.h2("Loading...")
elif item_query.error:
rendered_items = html.h2("Error when loading!")
else:
rendered_items = html.ul(html.li(item, key=item) for item in item_query.data)

item_mutation = use_mutation(add_item, refetch=get_items)
if item_mutation.loading:
mutation_status = html.h2("Adding...")
elif item_mutation.error:
mutation_status = html.h2("Error when adding!")
else:
mutation_status = ""

def submit_event(event):
if event["key"] == "Enter":
item_mutation.execute(text=event["target"]["value"])

return html.div(
html.label("Add an item:"),
html.input({"type": "text", "onKeyDown": submit_event}),
mutation_status,
rendered_items,
)
```

??? question "Can I make ORM calls without hooks?"

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a `SynchronousOnlyOperation` exception.

This may be resolved in a future version of Django with a natively asynchronous ORM.

However, even when resolved it is best practice to perform ORM queries within the `use_query` in order to handle `loading` and `error` states.

??? question "What is an "ORM"?"

A Python **Object Relational Mapper** is an API for your code to access a database.

See the [Django ORM documentation](https://docs.djangoproject.com/en/dev/topics/db/queries/) for more information.

## Use Websocket

You can fetch the Django Channels websocket at any time by using `use_websocket`.
Expand Down
52 changes: 0 additions & 52 deletions docs/features/orm.md

This file was deleted.

3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ nav:
- Components: features/components.md
- Hooks: features/hooks.md
- Decorators: features/decorators.md
- ORM: features/orm.md
- Template Tag: features/templatetag.md
- Settings: features/settings.md
- Contribute:
Expand Down Expand Up @@ -52,6 +51,8 @@ markdown_extensions:
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
- pymdownx.tabbed:
alternate_style: true
- pymdownx.highlight
- pymdownx.superfences
- pymdownx.details
Expand Down
14 changes: 7 additions & 7 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,35 +51,35 @@ def test_suite(session: Session) -> None:
session.env["IDOM_DEBUG_MODE"] = "1"

posargs = session.posargs[:]
if "--headless" in posargs:
posargs.remove("--headless")
session.env["SELENIUM_HEADLESS"] = "1"
if "--headed" in posargs:
posargs.remove("--headed")
session.env["PLAYWRIGHT_HEADED"] = "1"

if "--no-debug-mode" not in posargs:
posargs.append("--debug-mode")

session.run("playwright", "install", "chromium")
session.run("python", "manage.py", "test", *posargs)


@nox.session
def test_types(session: Session) -> None:
install_requirements_file(session, "check-types")
install_requirements_file(session, "pkg-deps")
session.run("mypy", "--show-error-codes", "src/django_idom", "tests/test_app")
session.run("mypy", "--show-error-codes", "src/django_idom")


@nox.session
def test_style(session: Session) -> None:
"""Check that style guidelines are being followed"""
install_requirements_file(session, "check-style")
session.run("flake8", "src/django_idom", "tests")
black_default_exclude = r"\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist"
session.run(
"black",
".",
"--check",
"--exclude",
rf"/({black_default_exclude}|venv|node_modules)/",
"--extend-exclude",
rf"/migrations/",
)
session.run("isort", ".", "--check-only")

Expand Down
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ line_length = 88
lines_after_imports = 2

[tool.mypy]
ignore_missing_imports = "True"
warn_unused_configs = "True"
warn_redundant_casts = "True"
warn_unused_ignores = "True"
ignore_missing_imports = true
warn_unused_configs = true
warn_redundant_casts = true
warn_unused_ignores = true
3 changes: 2 additions & 1 deletion requirements/build-docs.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mkdocs
mkdocs-git-revision-date-localized-plugin
mkdocs-material
mkdocs-include-markdown-plugin
mkdocs-include-markdown-plugin
linkcheckmd
3 changes: 2 additions & 1 deletion requirements/pkg-deps.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
channels >=3.0.0
idom >=0.39.0, <0.40.0
idom >=0.40.2, <0.41.0
aiofile >=3.0
typing_extensions
2 changes: 1 addition & 1 deletion requirements/test-env.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
django
selenium <= 4.2.0
playwright
twisted
Loading