0

django メッセージの単純なプッシュ プロトコルを実行しようとしています。したがって、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 ループは何もしません。これは、メッセージ フレームワークがセッション変数を再読み込みするだけで、新しいリクエストで「更新」するだけだからです。

その場でストレージを更新することについて何かあるかどうかを確認するために、基になるコードを調べてみましたが、少なくともメッセージング フレームワークでは、これを行うコードはないようです。この有望な文書化されていないstorage.update()方法がありましたが、別のことを行うことが判明しました。

では、Django フレームワークには、メッセージの変更をポーリングし、それが発生したときにそれをブラウザに報告できるものはありますか? または、同じことをよりエレガントに実現する別の方法はありますか?

4

1 に答える 1

1

私は、いくつかの注意を払って、許容できる解決策にたどり着きました。既存のメッセージ ストア (Cookie またはセッション) を使用することは、不可能 (Cookie) であるか、内部メソッド呼び出しと内部メンバーの設定/削除 (セッション) が多すぎることが判明しました。

このソリューションでは、新しいメッセージ ストア (私の場合はデータベース) を使用します。

設定.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]

内部的にはこれはまだポーリング ソリューションであることに注意してください (ループは常にメッセージをリロードします) が、概念を証明し、最終的には機能します。基礎となるストレージ/シグナルメカニズムの最適化は、この回答の範囲を超えています。

于 2016-10-06T15:11:42.510 に答える