Django Channels的聊天室

时间:2017-03-21 08:42:20

标签: javascript python django websocket django-channels

我有“Project”和“Room”模型。每个项目都有自己的聊天室。我想使用Django频道。不幸的是,我有错误。我想念的是什么,以及如何解决这个错误。

错误

Traceback (most recent call last):
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
    response = get_response(request)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\channels\handler.py", line 237, in process_exception_by_middleware
    return super(AsgiHandler, self).process_exception_by_middleware(exception, request)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\contrib\auth\decorators.py", line 23, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\Users\Nurzhan\PycharmProjects\RMS\project\views.py", line 176, in chat_room
    room, created = Room.objects.get_or_create(project=project_code)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 475, in get_or_create
    return self._create_object_from_params(lookup, params)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 505, in _create_object_from_params
    obj = self.create(**params)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 397, in create
    obj = self.model(**kwargs)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 537, in __init__
    setattr(self, field.name, rel_obj)
  File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\fields\related_descriptors.py", line 211, in __set__
    self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "'1744d0bc-e439-4562-9c29-4e7b2451f39c'": "Room.project" must be a "Project" instance.

urls.py

url(r'^(?P<project_code>[0-9a-f-]+)/chat_room/$', chat_room, name='chat_room'),

settings.py

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgi_redis.RedisChannelLayer",
        "CONFIG": {
            "hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
        },
        "ROUTING": "chat.routing.channel_routing",
    },
}

models.py

class Room(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)

    code = models.UUIDField(_('Code'), primary_key=True, default=uuid.uuid4, editable=False)

    def __str__(self):
        return self.code

    def get_absolute_url(self):
        return reverse('project:chat_room', args=[self.project_code])


class Message(models.Model):
    room = models.ForeignKey(Room, related_name='messages')

    handle = models.TextField()

    message = models.TextField()

    timestamp = models.DateTimeField(default=timezone.now, db_index=True)

    def __unicode__(self):
        return '[{timestamp}] {handle}: {message}'.format(**self.as_dict())

    def __str__(self):
        return self.__unicode__()

    @property
    def formatted_timestamp(self):
        return self.timestamp.strftime('%b %-d %-I:%M %p')

    def as_dict(self):
        return {'handle': self.handle, 'message': self.message, 'timestamp': self.formatted_timestamp}

views.py

def chat_room(request, project_code):
    # If the room with the given project_code doesn't exist, automatically create it upon first visit.
    room, created = Room.objects.get_or_create(project=project_code)

    # We want to show the last 50 messages, ordered most-recent-last
    messages = reversed(room.messages.order_by('-timestamp')[:50])

    return render(request, "project/chat/room.html", {
        'room': room,
        'messages': messages,
    })

consumers.py

@channel_session
def ws_connect(message):
    prefix, project_code = message['path'].strip('/').strip('/').strip('/').strip('/').strip('/').strip('/')
    room = Room.objects.get(project=project_code)
    message.reply_channel.send({"accept": True})
    Group('chat' + project_code).add(message.reply_channel)
    message.channel_session['room'] = room.project


@channel_session
def ws_receive(message):
    project_code = message.channel_session['room']
    room = Room.objects.get(project=project_code)
    data = json.loads(message['text'])
    m = room.messages.create(handle=data['handle'], message=data['message'])
    Group('chat' + project_code).send({'text': json.dumps(m.as_dict())})


@channel_session
def ws_disconnect(message):
    project_code = message.channel_session['room']
    Group('chat' + project_code).discard(message.reply_channel)

routing.py

channel_routing = [
    route("websocket.connect", ws_connect),
    route("websocket.receive", ws_receive),
    route("websocket.disconnect", ws_disconnect),
]

chat.js

$(document).ready(function(){
  socket = new WebSocket("ws://" + window.location.host + "/chat" + window.location.pathname);
  var name = "";

  swal({
    title: 'Your name:',
    input: 'text',
    inputValidator: function (value) {
      return new Promise(function (resolve, reject) {
        if (value) {
          resolve()
        } else {
          reject('You need to write something!')
        }
      })
    }
  }).then(function (result) {
    name = result;
    swal({
      type: 'success',
      html: 'Hello ' + result
    })
  });

  socket.onopen = function(){
    $('#chatform').on('submit', function(event) {
      var message = {
        handle: name,
        message: $('#message').val(),
      }
      socket.send(JSON.stringify(message));
      $('#message').val('');
      return false;
    });
  }

  socket.onmessage = function(message) {
    var data = JSON.parse(message.data);
    $('#chat').append('<tr>'
    + '<td>' + data.timestamp + '</td>'
    + '<td>' + data.handle + '</td>'
    + '<td>' + data.message + ' </td>'
    + '</tr>');
    Push.create("Django Channels Example | " + room , {
      body: "New Message",
      icon: 'http://pa1.narvii.com/6184/91c955faf54e625b3467093bea75a6d25b813871_128.gif',
      timeout: 4000,
      onClick: function () {
        window.focus();
        this.close();
      }
    });
  };

  if (socket.readyState == WebSocket.OPEN) socket.onopen();


});

0 个答案:

没有答案