diff --git a/flightmate/settings.py b/flightmate/settings.py
index 08fd384e165249006ea27d370b0e029abea3b495..0ece708a14dff99b8c5152e8936ad8bd2ac34f07 100755
--- a/flightmate/settings.py
+++ b/flightmate/settings.py
@@ -23,7 +23,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 SECRET_KEY = '#4h5=lswbghq65^otbpo16c^c1_@&winj16+nk+8naqc@dv-we'
 
 # SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
+DEBUG = False
 
 ALLOWED_HOSTS = ['*']
 
diff --git a/webapp/customers.py b/webapp/customers.py
index 4634ce54184355615db6a1c68975112b0fc63335..cbd9d48c8e6d70f9b82d53e06e3f2edf42815b5a 100644
--- a/webapp/customers.py
+++ b/webapp/customers.py
@@ -1,29 +1,82 @@
-# 当接收到前端发来的消息时,后端会触发ws_message函数
+import re
+import json
+import logging
 from channels import Group
-# def ws_message(message):
-#     # ASGI WebSocket packet-received and send-packet message types
-#     # both have a "text" key for their textual data.
-#     message.reply_channel.send({
-#         "text": message.content['text'],
-#     })
-
-# Connected to websocket.connect   websocket连接的时候进行的操作
-def ws_add(message):
-    # Any user connecting to our app will be added to the “users” group and will receive messages sent by the server.
-    message.reply_channel.send({"accept": True})
-    # Add to the chat group
-    Group("chat").add(message.reply_channel)
-
-# Connected to websocket.receive   收到消息的时候进行的操作
-def ws_message(message):
-    Group("chat").send({
-        "text": "[user] %s" % message.content['text'],
-    })
-
-# Connected to websocket.disconnect 关闭链接的时候进行的操作
-def ws_disconnect(message):
-    Group("chat").discard(message.reply_channel)
-    # When the client disconnects from our app, the channel is removed from the group, and the user will stop receiving messages.
-    # 这里利用了组的概念,在触发连接的时候,把其加入chat组,当收到消息时候,在组内所有用户发送信息,最后关闭连接的时候退出组。
+from channels.sessions import channel_session
+from .models import Room
+
+log = logging.getLogger(__name__)
+
+
+@channel_session
+def ws_connect(message):
+    # Extract the room from the message. This expects message.path to be of the
+    # form /chat/{label}/, and finds a Room if the message path is applicable,
+    # and if the Room exists. Otherwise, bails (meaning this is a some othersort
+    # of websocket). So, this is effectively a version of _get_object_or_404.
+    try:
+        prefix, label = message['path'].decode('ascii').strip('/').split('/')
+        if prefix != 'chat':
+            log.debug('invalid ws path=%s', message['path'])
+            return
+        room = Room.objects.get(label=label)
+    except ValueError:
+        log.debug('invalid ws path=%s', message['path'])
+        return
+    except Room.DoesNotExist:
+        log.debug('ws room does not exist label=%s', label)
+        return
+
+    log.debug('chat connect room=%s client=%s:%s',
+              room.label, message['client'][0], message['client'][1])
+
+    # Need to be explicit about the channel layer so that testability works
+    # This may be a FIXME?
+    Group('chat-' + label, channel_layer=message.channel_layer).add(message.reply_channel)
+
+    message.channel_session['room'] = room.label
+
 
+@channel_session
+def ws_receive(message):
+    # Look up the room from the channel session, bailing if it doesn't exist
+    try:
+        label = message.channel_session['room']
+        room = Room.objects.get(label=label)
+    except KeyError:
+        log.debug('no room in channel_session')
+        return
+    except Room.DoesNotExist:
+        log.debug('recieved message, buy room does not exist label=%s', label)
+        return
+
+    # Parse out a chat message from the content text, bailing if it doesn't
+    # conform to the expected message format.
+    try:
+        data = json.loads(message['text'])
+    except ValueError:
+        log.debug("ws message isn't json text=%s", text)
+        return
+
+    if set(data.keys()) != set(('handle', 'message')):
+        log.debug("ws message unexpected format data=%s", data)
+        return
+
+    if data:
+        log.debug('chat message room=%s handle=%s message=%s',
+                  room.label, data['handle'], data['message'])
+        m = room.messages.create(**data)
+
+        # See above for the note about Group
+        Group('chat-' + label, channel_layer=message.channel_layer).send({'text': json.dumps(m.as_dict())})
+
+
+@channel_session
+def ws_disconnect(message):
+    try:
+        label = message.channel_session['room']
+        room = Room.objects.get(label=label)
+        Group('chat-' + label, channel_layer=message.channel_layer).discard(message.reply_channel)
+    except (KeyError, Room.DoesNotExist):
+        pass
 
diff --git a/webapp/models.py b/webapp/models.py
index b73a104c7af9f90de4c910c7823d517cde3d4f81..516d5488da5642d57636248ca5a538dc5d3c6470 100755
--- a/webapp/models.py
+++ b/webapp/models.py
@@ -2,6 +2,7 @@ from __future__ import unicode_literals
 import uuid
 import datetime
 from django.db import models
+from django.utils import timezone
 
 class FlightRecords(models.Model):
     frid = models.IntegerField(default=0)
@@ -58,6 +59,30 @@ class FlightSeg(models.Model):
         self.full_clean()
         super(FlightSeg, self).save(*args, **kwargs)
 
+
+class Room(models.Model):
+    name = models.TextField()
+    label = models.SlugField(unique=True)
+
+    def __unicode__(self):
+        return self.label
+
+
+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())
+
+    @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}
 """
 class Reserved(models.Model):
     user = models.ForeignKey(User, verbose_name='user_reserved', on_delete=models.CASCADE)
diff --git a/webapp/urls.py b/webapp/urls.py
index da724a760d84b4111c3af4635010daf9d97516d1..3b7ff3c66a5ba59a0598a5f2366eda92fd69e3fe 100644
--- a/webapp/urls.py
+++ b/webapp/urls.py
@@ -1,6 +1,6 @@
 from django.conf.urls import include, url
 from webapp import views
-from .views import user_list
+from .views import log_in, log_out,sign_up, user_list
 
 urlpatterns = [
     url(r'^$', views.index, name='index'),
@@ -8,8 +8,11 @@ urlpatterns = [
     url(r'^mobileapp$', views.mobileapp, name='mobileapp'),
     url(r'^account$', views.account, name='account'),
     url(r'^trip$', views.trip, name='trip'),
-    #  link to user_list html
+    #  link to user_list html, login and logout
     url(r'^$', user_list, name='user_list'),
+    url(r'^log_in/$', log_in, name='log_in'),
+    url(r'^log_out/$', log_out, name='log_out'),
+    url(r'^sign_up/$', sign_up, name='sign_up'),
 ]
 
 
diff --git a/webapp/views.py b/webapp/views.py
index 72262f18ed1316146ace2abfd73cb0ef83176824..7bf95dcc755c8521ba2cc2ac13b72f362d074bc3 100755
--- a/webapp/views.py
+++ b/webapp/views.py
@@ -6,11 +6,43 @@ from webapp.helper import updateModel, doHash, user_auth
 from django.contrib.sessions.backends.db import SessionStore
 from django.contrib.sessions.models import Session
 import json, datetime
+from django.contrib.auth import login, logout
+from django.contrib.auth.forms import AuthenticationForm
+from django.core.urlresolvers import reverse
+from django.shortcuts import render, redirect
+from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
 
 
 def user_list(request):
     return render(request, 'example/user_list.html')
 
+def log_in(request):
+    form = AuthenticationForm()
+    if request.method == 'POST':
+        form = AuthenticationForm(data=request.POST)
+        if form.is_valid():
+            login(request, form.get_user())
+            return redirect(reverse('example:user_list'))
+        else:
+            print(form.errors)
+    return render(request, 'example/log_in.html', {'form': form})
+
+
+def log_out(request):
+    logout(request)
+    return redirect(reverse('example:log_in'))
+
+def sign_up(request):
+    form = UserCreationForm()
+    if request.method == 'POST':
+        form = UserCreationForm(data=request.POST)
+        if form.is_valid():
+            form.save()
+            return redirect(reverse('example:log_in'))
+        else:
+            print(form.errors)
+    return render(request, 'example/sign_up.html', {'form': form})
+
 def trip(request):
     user = None
     token = request.GET.get("token", "")
@@ -206,4 +238,44 @@ def query(request):
     return render(request, 'query.html', context)
 
 def mobileapp(request):
-    return render(request, 'mobileapp.html')
\ No newline at end of file
+    return render(request, 'mobileapp.html')
+
+import random
+import string
+from django.db import transaction
+from django.shortcuts import render, redirect
+import haikunator
+from .models import Room
+
+def about(request):
+    return render(request, "chat/about.html")
+
+def new_room(request):
+    """
+    Randomly create a new room, and redirect to it.
+    """
+    new_room = None
+    while not new_room:
+        with transaction.atomic():
+            label = haikunator.haikunate()
+            if Room.objects.filter(label=label).exists():
+                continue
+            new_room = Room.objects.create(label=label)
+    return redirect(chat_room, label=label)
+
+def chat_room(request, label):
+    """
+    Room view - show the room, with latest messages.
+    The template for this view has the WebSocket business to send and stream
+    messages, so see the template for where the magic happens.
+    """
+    # If the room with the given label doesn't exist, automatically create it
+    # upon first visit (a la etherpad).
+    room, created = Room.objects.get_or_create(label=label)
+
+    # We want to show the last 50 messages, ordered most-recent-last
+    messages = reversed(room.messages.order_by('-timestamp')[:50])
+
+    return render(request, "chat/room.html", {
+        'room': room,
+        'messages': messages,