Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

UserModel related hooks, decorators, and settings#190

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
65 commits
Select commitHold shift + click to select a range
6257c02
first draft of `use_user` and `use_user_data`
ArchmongerSep 18, 2023
2762345
misc
ArchmongerSep 18, 2023
72055e2
remove unneeded imports
ArchmongerSep 18, 2023
cb1c172
auth_required -> user_passes_test
ArchmongerSep 19, 2023
6815927
revert docs mods
ArchmongerSep 19, 2023
a1809d1
remove ComponentWebsocket
ArchmongerSep 19, 2023
81780dc
Merge remote-tracking branch 'upstream/main' into use-user-state-hook
ArchmongerSep 21, 2023
2f0735e
Simplify middleware requirements
ArchmongerSep 24, 2023
9a597a7
Merge remote-tracking branch 'upstream/main' into use-user-state-hook
ArchmongerSep 25, 2023
65119e3
fix changelog merge issue
ArchmongerSep 25, 2023
b32ca1a
fix circular import
ArchmongerSep 25, 2023
4d3b538
_UserDataType
ArchmongerSep 25, 2023
e2ae741
user_passes_test docstring
ArchmongerSep 25, 2023
b312ff6
fix docstrings for mutation and query hooks
ArchmongerSep 25, 2023
70c03b8
remove user_data_model type
ArchmongerSep 25, 2023
510f6a9
fix new mkdocs font color
ArchmongerSep 25, 2023
299f330
add warning to utils page
ArchmongerSep 25, 2023
a5b2a18
functional type hints
ArchmongerSep 26, 2023
b0bdbfc
use_user test
ArchmongerSep 26, 2023
f6abbbe
fix some bugs
ArchmongerSep 26, 2023
99a2a6d
fix broken type hint
ArchmongerSep 26, 2023
adfc583
tests for user_passes_test
ArchmongerSep 26, 2023
09dc565
Type hint for UserData as potentially None type
ArchmongerSep 26, 2023
29cccab
REACTPY_AUTO_LOGIN setting
ArchmongerSep 26, 2023
a516d7e
don't generate an exception for anonymous users
ArchmongerSep 27, 2023
a9d98d5
use orjson instead of dill for use_user_data
ArchmongerSep 27, 2023
41da464
REACTPY_AUTO_RELOGIN
ArchmongerSep 27, 2023
c2cc324
update REACTPY_AUTO_RELOGIN description
ArchmongerSep 27, 2023
bfab781
misc changelog updates
ArchmongerSep 27, 2023
7fc1af9
safer user_passes_test implementation
ArchmongerSep 28, 2023
e7b655f
fix bug where exception stacks would not print
ArchmongerSep 28, 2023
95d4062
user_passes_test docs
ArchmongerSep 28, 2023
b46a173
use_user_data test that passes manual testing
ArchmongerSep 28, 2023
b7481b5
merge migrations
ArchmongerSep 28, 2023
de70662
separate settings files for single/multi DB tests
ArchmongerSep 28, 2023
e62317b
use_user_data tests
ArchmongerSep 28, 2023
e7ef0bd
fix tests
ArchmongerSep 28, 2023
2beda54
DecoratorParamError
ArchmongerSep 28, 2023
dd408ac
change banner color
ArchmongerOct 5, 2023
8089f71
auto_save_defaults
ArchmongerOct 5, 2023
a660fc4
refactor use_user_data test
ArchmongerOct 5, 2023
2bd4ccd
add some more links
ArchmongerOct 5, 2023
17c4a09
auto-generate superuser for tests
ArchmongerOct 8, 2023
4f93fa7
user_pk = models.BinaryField
ArchmongerOct 8, 2023
3d791d9
use_user_data_with_default tests
ArchmongerOct 8, 2023
1429c68
fix user_pk cleanup schema
ArchmongerOct 9, 2023
eb237dd
fix lint errors
ArchmongerOct 9, 2023
728813d
add click delay
ArchmongerOct 9, 2023
aeaecc5
add django.request logging
ArchmongerOct 9, 2023
5b757bf
fix test
ArchmongerOct 9, 2023
357b473
new user data interface
ArchmongerOct 9, 2023
51da91d
Add docstrings
ArchmongerDec 13, 2023
de49947
update docs examples
ArchmongerDec 13, 2023
57d1bbe
finish Use User Data docs
ArchmongerDec 13, 2023
295cfdb
interface and docs changes
ArchmongerDec 13, 2023
3914b92
fix mypy error
ArchmongerDec 13, 2023
05ed7b4
docs tweaks
ArchmongerDec 14, 2023
2daf08f
todo
ArchmongerDec 14, 2023
201da96
new interface
ArchmongerJan 1, 2024
ac960cd
auto load settings files
ArchmongerJan 1, 2024
8030a29
basic docs
ArchmongerJan 6, 2024
f1aa07a
use new mutation interface
ArchmongerJan 6, 2024
d799615
default values docs
ArchmongerJan 7, 2024
fd64b77
fix todos
ArchmongerJan 7, 2024
922a69f
small fixes after self review
ArchmongerJan 7, 2024
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
34 changes: 25 additions & 9 deletionsCHANGELOG.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,22 +36,38 @@ Using the following categories, list your changes in this order:

### Added

- ReactPy components can now use SEO compatible rendering!
- `settings.py:REACTPY_PRERENDER` can be set to `True` to enable this behavior by default
- Or, you can enable it on individual components via the template tag: `{% component "..." prerender="True" %}`
- `reactpy_django.components.view_to_iframe` component has been added, which uses an `<iframe>` to render a Django view.
- `reactpy_django.utils.register_iframe` function has been added, which is mandatory to use alongside `reactpy_django.components.view_to_iframe`.
- SEO compatible rendering!
- `settings.py:REACTPY_PRERENDER` can be set to `True` to make components pre-render by default.
- Or, you can enable it on individual components via the template tag: `{% component "..." prerender="True" %}`.
- New `view_to_iframe` feature!
- `reactpy_django.components.view_to_iframe` uses an `<iframe>` to render a Django view.
- `reactpy_django.utils.register_iframe` tells ReactPy which views `view_to_iframe` can use.
- New Django `User` related features!
- `reactpy_django.hooks.use_user` can be used to access the current user.
- `reactpy_django.hooks.use_user_data` provides a simplified interface for storing user key-value data.
- `reactpy_django.decorators.user_passes_test` is inspired by the [equivalent Django decorator](http://docs.djangoproject.com/en/dev/topics/auth/default/#django.contrib.auth.decorators.user_passes_test), but ours works with ReactPy components.
- `settings.py:REACTPY_AUTO_RELOGIN` will cause component WebSocket connections to automatically [re-login](https://channels.readthedocs.io/en/latest/topics/authentication.html#how-to-log-a-user-in-out) users that are already authenticated. This is useful to continuously update `last_login` timestamps and refresh the [Django login session](https://docs.djangoproject.com/en/dev/topics/http/sessions/).

### Changed

- Renamed undocumented utility function `reactpy_django.utils.ComponentPreloader` to `reactpy_django.utils.RootComponentFinder`.
- Renamed undocumented utility function `ComponentPreloader` to `RootComponentFinder`.
- It is now recommended to call `as_view()` when using `view_to_component` or `view_to_iframe` with Class Based Views.
- Thread sensitivity has been enabled in all locations where ORM queries are possible.
- For thread safety, `thread_sensitive=True` has been enabled in all `sync_to_async` functions where ORM queries are possible.
- `reactpy_django.hooks.use_mutation` now has a `__call__` method. So rather than writing `my_mutation.execute(...)`, you can now write `my_mutation(...)`.

### Deprecated

- The `compatibility` argument on `reactpy_django.components.view_to_component` is deprecated. Use `reactpy_django.components.view_to_iframe` instead.
- Using `reactpy_django.components.view_to_component` as a decorator is deprecated. Check the docs on the new suggested usage.
- The `compatibility` argument on `reactpy_django.components.view_to_component` is deprecated.
- Use `view_to_iframe` as a replacement.
- `reactpy_django.components.view_to_component` **usage as a decorator** is deprecated.
- Check the docs on how to use `view_to_component` as a function instead.
- `reactpy_django.decorators.auth_required` is deprecated.
- Use `reactpy_django.decorators.user_passes_test` instead.
- An equivalent to `auth_required`'s default is `@user_passes_test(lambda user: user.is_active)`.

### Fixed

- Fixed a bug where exception stacks would not print on failed component renders.

## [3.5.1] - 2023-09-07

Expand Down
3 changes: 3 additions & 0 deletionsdocs/overrides/home.html
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -58,6 +58,9 @@ <h1>{{ config.site_name }}</h1>
<a href="{{ 'reference/components/' | url }}" class="md-button">
API Reference
</a>
<a href="{{ 'about/changelog/' | url }}" class="md-button">
Changelog
</a>
</div>
</div>

Expand Down
8 changes: 0 additions & 8 deletionsdocs/python/auth-required-attribute.py
View file
Open in desktop

This file was deleted.

7 changes: 0 additions & 7 deletionsdocs/python/auth-required-custom-attribute-model.py
View file
Open in desktop

This file was deleted.

8 changes: 0 additions & 8 deletionsdocs/python/auth-required-custom-attribute.py
View file
Open in desktop

This file was deleted.

8 changes: 0 additions & 8 deletionsdocs/python/auth-required-vdom-fallback.py
View file
Open in desktop

This file was deleted.

8 changes: 0 additions & 8 deletionsdocs/python/auth-required.py
View file
Open in desktop

This file was deleted.

9 changes: 3 additions & 6 deletionsdocs/python/configure-asgi-middleware.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@

# start
from channels.auth import AuthMiddlewareStack # noqa: E402
from channels.sessions import SessionMiddlewareStack # noqa: E402

application = ProtocolTypeRouter(
{
"http": django_asgi_app,
"websocket": SessionMiddlewareStack(
AuthMiddlewareStack(
URLRouter(
[REACTPY_WEBSOCKET_ROUTE],
)
"websocket": AuthMiddlewareStack(
URLRouter(
[REACTPY_WEBSOCKET_ROUTE],
)
),
}
Expand Down
5 changes: 3 additions & 2 deletionsdocs/python/use-connection.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,5 +4,6 @@

@component
def my_component():
my_connection = use_connection()
return html.div(str(my_connection))
connection = use_connection()

return html.div(str(connection))
5 changes: 3 additions & 2 deletionsdocs/python/use-location.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,5 +4,6 @@

@component
def my_component():
my_location = use_location()
return html.div(str(my_location))
location = use_location()

return html.div(str(location))
2 changes: 1 addition & 1 deletiondocs/python/use-mutation-args-kwargs.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,6 @@ def example_mutation(value: int, other_value: bool = False):
def my_component():
mutation = use_mutation(example_mutation)

mutation.execute(123, other_value=True)
mutation(123, other_value=True)

...
4 changes: 2 additions & 2 deletionsdocs/python/use-mutation-query-refetch.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,7 +18,7 @@ def todo_list():

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

# Handle all possible query states
if item_query.loading:
Expand All@@ -38,7 +38,7 @@ def submit_event(event):

return html.div(
html.label("Add an item:"),
html.input({"type": "text", "onKeyDown": submit_event}),
html.input({"type": "text", "on_key_down": submit_event}),
mutation_status,
rendered_items,
)
6 changes: 3 additions & 3 deletionsdocs/python/use-mutation-reset.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,17 +16,17 @@ def reset_event(event):

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

if item_mutation.loading:
mutation_status = html.h2("Adding...")
elif item_mutation.error:
mutation_status = html.button({"onClick": reset_event}, "Error: Try again!")
mutation_status = html.button({"on_click": reset_event}, "Error: Try again!")
else:
mutation_status = html.h2("Mutation done.")

return html.div(
html.label("Add an item:"),
html.input({"type": "text", "onKeyDown": submit_event}),
html.input({"type": "text", "on_key_down": submit_event}),
mutation_status,
)
4 changes: 2 additions & 2 deletionsdocs/python/use-mutation-thread-sensitive.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ def my_component():

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

if item_mutation.loading or item_mutation.error:
mutation_status = html.h2("Doing something...")
Expand All@@ -27,6 +27,6 @@ def submit_event(event):
mutation_status = html.h2("Done.")

return html.div(
html.input({"type": "text", "onKeyDown": submit_event}),
html.input({"type": "text", "on_key_down": submit_event}),
mutation_status,
)
4 changes: 2 additions & 2 deletionsdocs/python/use-mutation.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,7 +13,7 @@ def todo_list():

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

if item_mutation.loading:
mutation_status = html.h2("Adding...")
Expand All@@ -24,6 +24,6 @@ def submit_event(event):

return html.div(
html.label("Add an item:"),
html.input({"type": "text", "onKeyDown": submit_event}),
html.input({"type": "text", "on_key_down": submit_event}),
mutation_status,
)
5 changes: 3 additions & 2 deletionsdocs/python/use-origin.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,5 +4,6 @@

@component
def my_component():
my_origin = use_origin()
return html.div(my_origin or "No origin")
origin = use_origin()

return html.div(origin or "No origin")
5 changes: 3 additions & 2 deletionsdocs/python/use-scope.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,5 +4,6 @@

@component
def my_component():
my_scope = use_scope()
return html.div(str(my_scope))
scope = use_scope()

return html.div(str(scope))
25 changes: 25 additions & 0 deletionsdocs/python/use-user-data-defaults.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
from reactpy import component, html
from reactpy_django.hooks import use_user_data


@component
def my_component():
user_data = use_user_data(
default_data={
"basic_example": "123",
"computed_example_sync": sync_default,
"computed_example_async": async_default,
}
)

return html.div(
html.div(f"Data: {user_data.query.data}"),
)


def sync_default():
return ...


async def async_default():
return ...
19 changes: 19 additions & 0 deletionsdocs/python/use-user-data.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
from reactpy import component, html
from reactpy_django.hooks import use_user_data


@component
def my_component():
query, mutation = use_user_data()

def on_submit(event):
if event["key"] == "Enter" and query.data:
new_key = str(len(query.data))
mutation({**query.data, new_key: event["target"]["value"]})

return html.div(
html.div(f"Data: {query.data}"),
html.div(f"Loading: {query.loading | mutation.loading}"),
html.div(f"Error(s): {query.error} {mutation.error}"),
html.input({"on_key_press": on_submit}),
)
9 changes: 9 additions & 0 deletionsdocs/python/use-user.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
from reactpy import component, html
from reactpy_django.hooks import use_user


@component
def my_component():
user = use_user()

return html.div(user.username)
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
from reactpy import component, html
from reactpy_django.decorators importauth_required
from reactpy_django.decorators importuser_passes_test


@component
def my_component_fallback():
return html.div("I am NOT logged in!")


def auth_check(user):
return user.is_authenticated


@user_passes_test(auth_check, fallback=my_component_fallback)
@component
@auth_required(fallback=my_component_fallback)
def my_component():
return html.div("I am logged in!")
12 changes: 12 additions & 0 deletionsdocs/python/user-passes-test-vdom-fallback.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
from reactpy import component, html
from reactpy_django.decorators import user_passes_test


def auth_check(user):
return user.is_authenticated


@user_passes_test(auth_check, fallback=html.div("I am NOT logged in!"))
@component
def my_component():
return html.div("I am logged in!")
12 changes: 12 additions & 0 deletionsdocs/python/user-passes-test.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
from reactpy import component, html
from reactpy_django.decorators import user_passes_test


def auth_check(user):
return user.is_authenticated


@user_passes_test(auth_check)
@component
def my_component():
return html.div("I am logged in!")
2 changes: 1 addition & 1 deletiondocs/src/assets/css/banner.css
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
body[data-md-color-scheme="slate"] {
--md-banner-bg-color:#4d4121;
--md-banner-bg-color:rgb(55, 81, 78);
--md-banner-font-color: #fff;
}

Expand Down
5 changes: 3 additions & 2 deletionsdocs/src/assets/css/main.css
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,6 +17,7 @@
--md-default-bg-color--lighter: hsla(var(--md-hue), 15%, 16%, 0.26);
--md-default-bg-color--lightest: hsla(var(--md-hue), 15%, 16%, 0.07);
--md-primary-fg-color: var(--md-default-bg-color);
--md-default-fg-color: hsla(var(--md-hue), 75%, 95%, 1);
--md-default-fg-color--light: #fff;
--md-typeset-a-color: var(--reactpy-color);
--md-accent-fg-color: var(--reactpy-color-dark);
Expand All@@ -38,7 +39,7 @@
}

.md-typeset h1 {
font-weight:500;
font-weight:600;
margin: 0;
font-size: 2.5em;
}
Expand All@@ -48,7 +49,7 @@
}

.md-typeset h3 {
font-weight:600;
font-weight:400;
}

/* Intro section styling */
Expand Down
6 changes: 3 additions & 3 deletionsdocs/src/learn/add-reactpy-to-a-django-project.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -77,15 +77,15 @@ Register ReactPy's WebSocket using `#!python REACTPY_WEBSOCKET_ROUTE` in your [`
{% include "../../python/configure-asgi.py" %}
```

??? info "Add `#!python AuthMiddlewareStack`and `#!python SessionMiddlewareStack`(Optional)"
??? info "Add `#!python AuthMiddlewareStack` (Optional)"

There are many situations where you need to access the Django `#!python User` or `#!python Session` objects within ReactPy components. For example, if you want to:

1. Access the `#!python User` that is currently logged in
2. Login or logout the current `#!python User`
3. Access Django's `#!python Session` object
2. Login or logout the current `#!python User`

In these situations will need to ensure you are using `#!python AuthMiddlewareStack` and/or `#!python SessionMiddlewareStack`.
In these situations will need to ensure you are using `#!python AuthMiddlewareStack`.

```python linenums="0"
{% include "../../python/configure-asgi-middleware.py" start="# start" %}
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp