Djangoチャンネルでの作業を開始します。私のモデルのデバイスのバインドデータが必要です。私がやる。管理インタフェースでDeviceオブジェクトを変更すると、クライアント(Webブラウザ)で変更に関するメッセージが表示されますが、カスタムdjango管理コマンドを使用して簡単なWebsocketServerも実行します。また、カスタムコマンド処理でDevice-objectが変更された場合、私はクライアントにメッセージを受け取らない。どのように私はそれを修正することができます?カスタムコマンドのDjangoチャンネルによるデータバインド
デバイス/ models.py
OFFLINE = 0
ONLINE = 1
REGISTRATION = 2
REMOVED = 3
ERROR = 4
STATUS_CHOICES = (
(OFFLINE, _("Offline")),
(ONLINE, _("Online")),
(REGISTRATION, _("Registration")),
(REMOVED, _("Removed")),
(ERROR, _("Error")),
)
class Device(models.Model):
name = models.CharField(max_length=128,
null=True, blank=True, default=None, verbose_name=_("Name"))
created = models.DateTimeField(verbose_name=_("Creation date time"), editable=False)
modified = models.DateTimeField(verbose_name=_("Last change date time"), blank=True)
removed = models.BooleanField(verbose_name=_("Device has been removed"), default=False)
remove_date = models.DateTimeField(verbose_name=_("Date of Device removing"),
null=True, blank=True,
default=None)
joined = models.BooleanField(verbose_name=_("Registration status"), default=False)
date_joined = models.DateTimeField(verbose_name=_("Registration date time"), blank=True, null=True, default=None)
owner = models.ForeignKey("accounts.User",
null=True, blank=True, default=None,
verbose_name=_("Who registered"), on_delete=models.SET(None))
status = models.SmallIntegerField(choices=STATUS_CHOICES, blank=True, default=REGISTRATION, verbose_name=_("Status"))
frozen = models.BooleanField(default=False, verbose_name=_("Device is frozen"))
デバイス/ databinding.py
from channels.binding.websockets import WebsocketBinding
from .models import Device
class DeviceBinding(WebsocketBinding):
model = Device
stream = "device"
fields = ['status', 'joined', 'frozen']
@classmethod
def group_names(cls, *args, **kwargs):
return ["binding.devices"]
def has_permission(self, user, action, pk):
return True # FIXME: check permission for user
プロジェクト/ routing.py
from channels import route_class, route
from devices.consumers import Demultiplexer
from devices.databinding import DeviceBinding
channel_routing = [
route_class(Demultiplexer, path='^/stream/?$'),
route("binding.device", DeviceBinding.consumer),
]
デバイス/ consumers.py
from channels.generic.websockets import WebsocketDemultiplexer
class Demultiplexer(WebsocketDemultiplexer):
mapping = {
"device": "binding.device",
}
def connection_groups(self):
return ["binding.devices"]
My autobahn WebSockerServerを実行する簡単なカスタムコマンドです。
プロジェクト/管理/コマンド/ runcustomcommand.py
from django.core.management import BaseCommand
from project.websocketserver.autobahn_server import WebSocketServer
class Command(BaseCommand):
help = "Run WebSocket Server"
# A command must define handle()
def handle(self, *args, **options):
wss = WebSocketServer()
wss.start()
プロジェクト/ websocketserver/autobahn_server.py
クラスWebSocketServer(オブジェクト):
def __init__(self):
import sys
from twisted.python import log
log.startLogging(sys.stdout)
self.factory = WebSocketServerFactory(
"ws://{host}:{port}".format(
host=settings.WSS_HOST, port=settings.WSS_PORT),
# debug=False
)
self.factory.protocol = MyServerProtocol
self.factory.setProtocolOptions(
autoPingInterval=settings.WSS_AUTO_PING_INTERVAL,
autoPingTimeout=settings.WSS_AUTO_PING_TIMEOUT
)
def start(self):
from twisted.internet import reactor
try:
logger.info("\tSTART SERVER")
reactor.listenTCP(settings.WSS_PORT, self.factory)
reactor.run()
except KeyboardInterrupt:
pass
finally:
self.stop()
def stop(self):
from twisted.internet import reactor
reactor.stop()
logger.info("\tSTOP SERVER")
クライアント上のconnetion(JSコード):
var ws_path = "ws://127.0.0.1:8001/stream/";
console.log("Connecting to " + ws_path);
var webSocket = new WebSocket(ws_path);
webSocket.onopen = function() {
alert("Connected!.");
};
webSocket.onmessage = function(message) {
var data = JSON.parse(message.data);
alert(data);
};
webSocket.onerror = function(error) {
alert("Error: " + error.message);
};
私が実行します。
redis-server
daphne project.asgi:channel_layer --port 8001
python manage.py runworker -v2
python manage.py runserver 0.0.0.0:8000 -v2
python manage.py runcustomcommand
UPDATE
私が誤って自分の管理コマンドの開始でこのコードを追加した場合、オブジェクトへの後続の変更がクライアントに来ることを発見:
from channels import Channel
Channel("binding.devices").send({})
初期化のようなものです。しかし、それは不思議です。