Каналы Django + HTMX -> фреймворк уведомлений
Я хотел бы реализовать фреймворк уведомлений для Django, который использует каналы/вебсокеты и HTMX. Но я не понимаю, как это сделать. Некоторые вещи работают, некоторые чрезвычайно сложны, по крайней мере, для моего ума. Вот код:
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from channels.layers import get_channel_layer
from django.contrib import messages
from django.template.loader import get_template
from medux.common.models import User
class NotificationConsumer(WebsocketConsumer):
def connect(self):
self.user = self.scope["user"]
if not self.user.is_authenticated:
self.close()
return
# create a group "user-<username>"
async_to_sync(self.channel_layer.group_add)(
f"user-{self.user.username}",
self.channel_name,
)
self.accept()
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(
f"user-{self.user.username}",
self.channel_name,
)
def notify(self, event: dict):
html = get_template("common/toast.html").render(
context={"message": event["message"]}
)
self.send(text_data=html)
<div hx-ext="ws" ws-connect="/ws/messages">
<div id="toasts" class="toast-container position-fixed bottom-0 end-0 p-3 pb-5">
{% for message in messages %}
<div
id="toasts"
hx-swap-oob="beforeend">
<div
data-toast-template
class="toast align-items-center border-0 show"
role="alert"
aria-live="assertive"
aria-atomic="true">
{# header here #}
<div data-toast-body class="toast-body">{{ message }}</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
{% endfor %}
</div>
</div>
Клиент подключается к потребителю, и если я напишу небольшое `self.send(text_data="foo")
AFAIK, мне нужно отправить потребителю событие "высокого уровня" с типом "notify", поэтому вызывается метод notify()
. Таким образом, это будет код, вызываемый в любом месте представления, например:
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"user-christian",
{"type": "notify", "message": "<div id='toasts' hx-swap-oob='beforeend'>blah</div>"}
)
Я не могу разобраться во внутреннем устройстве каналов, как бы часто я ни читал документацию.
Документация по использованию group_add
и group_send
скудна, и я уверен, что использую их неправильно.
Может ли кто-нибудь дать мне несколько подсказок здесь? На следующем этапе я бы заменил фреймворк обмена сообщениями Django на это решение в моем приложении.
Я добился того, чтобы эти вещи работали с Turbo Django, с которым довольно удобно работать, но в нем отсутствуют триггеры, такие как HTMX, которые позволяют мне инициировать вызовы AJAX, такие как hx-post или hx-get.