2016-12-06 35 views
1

我開始使用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"] 

我運行自定義高速公路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") 

在客戶端引黃(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({}) 

這就像某種初始化。但這很奇怪。

回答

0

我有這個完全相同的東西,但我不能肯定地說它可能是你的DeviceBinding.group_namesDemultiplexer.connection_groups方法不返回列表。確保他們有尾隨逗號["binding.device", ]["binding.devices", ]。除此之外,我可以看到的唯一區別是,我使用了不同的組名,因爲我有多個模型綁定和簡單使用的一組。

希望有幫助, Stu