Skip to content

Commit 14d5070

Browse files
committed
Fix Django ORM usage within components
1 parent b9ca296 commit 14d5070

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

src/django_idom/layout.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import os
2+
3+
from idom.core.layout import Layout, LayoutUpdate
4+
5+
6+
class DjangoLayout(Layout):
7+
"""Fixes Django ORM usage within components.
8+
These issues are caused by async/sync mixed context limitations in the ORM.
9+
Without this, `SynchronousOnlyOperation` exceptions occur when using the ORM in IDOM components.
10+
This may be fixed in a future version, such as Django 5.0."""
11+
12+
def _create_layout_update(self, old_state) -> LayoutUpdate:
13+
"""Create a layout update, but set ALLOW ASYNC UNSAFE flags prior.
14+
This allows the Django ORM to be used within components."""
15+
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
16+
layout_update = super()._create_layout_update(old_state)
17+
os.environ.pop("DJANGO_ALLOW_ASYNC_UNSAFE")
18+
return layout_update

src/django_idom/websocket/consumer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
from channels.auth import login
99
from channels.db import database_sync_to_async as convert_to_async
1010
from channels.generic.websocket import AsyncJsonWebsocketConsumer
11-
from idom.core.layout import Layout, LayoutEvent
11+
from idom.core.layout import LayoutEvent
1212
from idom.core.serve import serve_json_patch
1313

1414
from django_idom.config import IDOM_REGISTERED_COMPONENTS
1515
from django_idom.hooks import IdomWebsocket, WebsocketContext
16+
from django_idom.layout import DjangoLayout
1617

1718

1819
_logger = logging.getLogger(__name__)
@@ -73,7 +74,7 @@ async def _run_dispatch_loop(self):
7374
self._idom_recv_queue = recv_queue = asyncio.Queue()
7475
try:
7576
await serve_json_patch(
76-
Layout(WebsocketContext(component_instance, value=socket)),
77+
DjangoLayout(WebsocketContext(component_instance, value=socket)),
7778
self.send_json,
7879
recv_queue.get,
7980
)

0 commit comments

Comments
 (0)