Django 刷新会话以获取用户的任何新消息
Django refresh session to obtain any new messages for user
我正在尝试为 django messages 做一个简单的推送协议。所以在我的 REST 调用中,我有以下代码片段:
storage = get_messages(self.request)
res = dict(messages=[dict(level=item.level, message=item.message) for item in storage])
now = monotonic()
while not res.messages and monotonic() - now < 15:
sleep(.5)
res.messages = [dict(level=item.level, message=item.message) for item in storage]
自然地,while 循环什么都不做,因为消息框架只是重新读取会话变量,它只在新请求时 "updates"。
我尝试进入底层代码,看看是否有关于动态更新存储的任何内容,但似乎没有代码可以执行此操作,至少在消息传递框架中是这样。有一个很有前途的未记录的 storage.update()
方法,但结果却做了其他事情。
那么,Django 框架中是否有任何功能允许我轮询任何消息更改并在发生时向浏览器报告?或者可以更优雅地实现相同目的的不同方法?
我已经设法找到了一个可以接受的解决方案,但有几个注意事项。
使用现有消息存储(cookie 或会话)被证明要么是不可能的(cookie),要么被内部方法调用和设置/删除内部成员(会话)所困扰。
此解决方案使用新的消息存储,在我的例子中是数据库。
settings.py
MESSAGE_STORAGE = 'your_django_app.messages_store.SessionDBStorage'
your_django_app/messages_store.py
from django.contrib.messages.storage.session import SessionStorage
from main.models import MessagesStore, models
class SessionDBStorage(SessionStorage):
"""
Stores messages in the database based on session id
"""
def _get(self, *args, **kwargs):
"""
Retrieves a list of messages from the database based on session identifier.
"""
try:
return self.deserialize_messages(
MessagesStore.objects.get(pk=self.request.session.session_key).messages), True
except models.ObjectDoesNotExist:
return [], True
def _store(self, messages, response, *args, **kwargs):
"""
Stores a list of messages to the database.
"""
if messages:
MessagesStore.objects.update_or_create(session_key=self.request.session.session_key,
defaults={'messages': self.serialize_messages(messages)})
else:
MessagesStore.objects.filter(pk=self.request.session.session_key).delete()
return []
your_django_app/rest.py
def pushed_messages():
from time import sleep, monotonic
# standard get messages code
....
now = monotonic()
while not res.messages and monotonic() - now < 15:
sleep(1)
if hasattr(storage, '_loaded_data'): # one last hack to make storage reload messages
delattr(storage, '_loaded_data')
res.messages = [dict(level=item.level, message=item.message) for item in storage]
请注意,这在内部仍然是一个轮询解决方案(循环不断地重新加载消息),但它证明了这个概念并最终 - 有效。任何底层存储/信号机制优化都超出了这个答案的范围。
我正在尝试为 django messages 做一个简单的推送协议。所以在我的 REST 调用中,我有以下代码片段:
storage = get_messages(self.request)
res = dict(messages=[dict(level=item.level, message=item.message) for item in storage])
now = monotonic()
while not res.messages and monotonic() - now < 15:
sleep(.5)
res.messages = [dict(level=item.level, message=item.message) for item in storage]
自然地,while 循环什么都不做,因为消息框架只是重新读取会话变量,它只在新请求时 "updates"。
我尝试进入底层代码,看看是否有关于动态更新存储的任何内容,但似乎没有代码可以执行此操作,至少在消息传递框架中是这样。有一个很有前途的未记录的 storage.update()
方法,但结果却做了其他事情。
那么,Django 框架中是否有任何功能允许我轮询任何消息更改并在发生时向浏览器报告?或者可以更优雅地实现相同目的的不同方法?
我已经设法找到了一个可以接受的解决方案,但有几个注意事项。 使用现有消息存储(cookie 或会话)被证明要么是不可能的(cookie),要么被内部方法调用和设置/删除内部成员(会话)所困扰。
此解决方案使用新的消息存储,在我的例子中是数据库。
settings.py
MESSAGE_STORAGE = 'your_django_app.messages_store.SessionDBStorage'
your_django_app/messages_store.py
from django.contrib.messages.storage.session import SessionStorage
from main.models import MessagesStore, models
class SessionDBStorage(SessionStorage):
"""
Stores messages in the database based on session id
"""
def _get(self, *args, **kwargs):
"""
Retrieves a list of messages from the database based on session identifier.
"""
try:
return self.deserialize_messages(
MessagesStore.objects.get(pk=self.request.session.session_key).messages), True
except models.ObjectDoesNotExist:
return [], True
def _store(self, messages, response, *args, **kwargs):
"""
Stores a list of messages to the database.
"""
if messages:
MessagesStore.objects.update_or_create(session_key=self.request.session.session_key,
defaults={'messages': self.serialize_messages(messages)})
else:
MessagesStore.objects.filter(pk=self.request.session.session_key).delete()
return []
your_django_app/rest.py
def pushed_messages():
from time import sleep, monotonic
# standard get messages code
....
now = monotonic()
while not res.messages and monotonic() - now < 15:
sleep(1)
if hasattr(storage, '_loaded_data'): # one last hack to make storage reload messages
delattr(storage, '_loaded_data')
res.messages = [dict(level=item.level, message=item.message) for item in storage]
请注意,这在内部仍然是一个轮询解决方案(循环不断地重新加载消息),但它证明了这个概念并最终 - 有效。任何底层存储/信号机制优化都超出了这个答案的范围。