基础项目部署参考:点击打开链接
1、下载相应插件:
pip install channels
pip install asgi_redis
2、部署基本项目:
3、目录结构如下:
4、setting py 增加配置:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'demo',
]
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'asgi_redis.RedisChannelLayer',
'CONFIG': {
'hosts': [('127.0.0.1', 6379)],
},
'ROUTING': 'busymonkey.routing.channel_routing',
}
}
5、routing py :
from channels.routing import route
from demo.consumers import ws_connect, ws_disconnect, ws_receive
channel_routing = [
route('websocket.connect', ws_connect),
route("websocket.receive", ws_receive),
route('websocket.disconnect', ws_disconnect),
]
6、comsumers py :
import json
from channels import Group
from channels.auth import channel_session_user, channel_session_user_from_http
@channel_session_user_from_http
def ws_connect(message):
groupPath = message.content['path'][1:-1]
Group(groupPath).add(message.reply_channel)
Group(groupPath).send({
'text': json.dumps({
'username': message.user.username,
'is_logged_in': True
})
})
def ws_receive(message):
groupPath = message.content['path'][1:-1]
Group(groupPath).send({
'text': json.dumps({
'content': message.content['text'],
})
})
@channel_session_user
def ws_disconnect(message):
groupPath = message.content['path'][1:-1]
Group(groupPath).send({
'text': json.dumps({
'username': message.user.username,
'is_logged_in': False
})
})
Group(groupPath).discard(message.reply_channel)
7、urls py :
from django.conf.urls import url
from django.contrib import admin
from demo import views as demo_views
urlpatterns = [
url(r'^user_list/$', demo_views.user_list, name='user_list'),
url(r'^log_in/$', demo_views.log_in, name='log_in'),
url(r'^log_out/$', demo_views.log_out, name='log_out'),
url(r'^sign_up/$', demo_views.sign_up, name='sign_up'),
url(r'^admin/', admin.site.urls),
]
8、wsgi py :
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "busymonkey.settings")
application = get_wsgi_application()
9、apps py :
from __future__ import unicode_literals
from django.apps import AppConfig
class DemoConfig(AppConfig):
name = 'demo'
def ready(self):
import demo.signals
10、models.py :
from __future__ import unicode_literals
from django.conf import settings
from django.db import models
# Create your models here.
class LoggedInUser(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, related_name='logged_in_user')
11、signals.py :
from django.contrib.auth import user_logged_in, user_logged_out
from django.dispatch import receiver
from demo.models import LoggedInUser
@receiver(user_logged_in)
def on_user_login(sender, **kwargs):
LoggedInUser.objects.get_or_create(user=kwargs.get('user'))
@receiver(user_logged_out)
def on_user_logout(sender, **kwargs):
LoggedInUser.objects.filter(user=kwargs.get('user')).delete()
12、views.py :
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# Create your views here.
from django.contrib.auth import get_user_model, login, logout
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.shortcuts import redirect, render
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
User = get_user_model()
@login_required(login_url='/log_in/')
def user_list(request):
"""
NOTE: This is fine for demonstration purposes, but this should be
refactored before we deploy this app to production.
Imagine how 100,000 users logging in and out of our app would affect
the performance of this code!
"""
name = request.session.get('user', False)
users = User.objects.select_related('logged_in_user')
for user in users:
user.status = 'Online' if hasattr(user, 'logged_in_user') else 'Offline'
return render(request, 'user_list.html', {'users': users, 'user': name})
def log_in(request):
form = AuthenticationForm()
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
login(request, form.get_user())
request.session['user'] = form.get_user().__str__()
return redirect(reverse('user_list'))
else:
print(form.errors)
return render(request, 'log_in.html', {'form': form})
@login_required(login_url='/log_in/')
def log_out(request):
logout(request)
return redirect(reverse('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('log_in'))
else:
print(form.errors)
return render(request, 'sign_up.html', {'form': form})
13、log_in.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="{% url 'log_in' %}" method="post">
{% csrf_token %}
{% for field in form %}
<div>
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<button type="submit">Log in</button>
</form>
<p>Don't have an account? <a href="{% url 'sign_up' %}">Sign up!</a></p>
</body>
</html>
14、sign_up.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
{% block content %}
<form action="{% url 'sign_up' %}" method="post">
{% csrf_token %}
{% for field in form %}
<div>
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<button type="submit">Sign up</button>
<p>Already have an account? <a href="{% url 'log_in' %}">Log in!</a></p>
</form>
{% endblock content %}
</body>
</html>
15、user_list.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="/static/js/jquery-3.1.1.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
<script src="/static/js/loginJS.js"></script>
</head>
<script>
$(document).ready(function () {
var test = new EventTrigger();
test.init();
})
</script>
<body>
<a href="{% url 'log_out' %}">Log out</a>
<p id="userName">userName : {{ user }}</p>
<br>
<ul>
{% for user in users %}
<!-- NOTE: We escape HTML to prevent XSS attacks. -->
<li data-username="{{ user.username|escape }}">
{{ user.username|escape }}: {{ user.status|default:'Offline' }}
</li>
{% endfor %}
</ul>
<textarea id="chatWin" rows="20" cols="100"> </textarea>
<input id="chatName" type="text" />
<button id="openChatRoomBtn" type="button" >open chat room</button>
<input id="sendInput" type="text" />
<button id="sendBtn" type="button" >send</button>
</body>
</html>
16、 loginJS:
/**
* Created by Hou on 2017/4/10.
*/
function EventTrigger() {
}
EventTrigger.prototype.init = function () {
var socket = new WebSocket('ws://' + window.location.host + '/open/');
$("#openChatRoomBtn").click(function() {
var text = $("#chatName").val();
socket = new WebSocket('ws://' + window.location.host + '/'+ text +'/');
socket.onopen();
});
socket.onopen = function open() {
console.log('WebSockets connection created.');
};
socket.onmessage = function message(event) {
var data = JSON.parse(event.data);
// NOTE: We escape JavaScript to prevent XSS attacks.
var username = encodeURI(data['username']);
var content = data['content'];
var user = $('li').filter(function () {
return $(this).data('username') == username;
});
if (data['is_logged_in']) {
user.html(username + ': Online');
}
else {
user.html(username + ': Offline');
}
if (content != null && content != "") {
var text = $("#chatWin").val();
$("#chatWin").val(text+"\r\n"+content);
}
};
if (socket.readyState == WebSocket.OPEN) {
socket.onopen();
}
$("#sendBtn").click(function() {
var text = $("#sendInput").val();
socket.send(text);
});
}
17、loginCSS:
.Alert-Pwd-Error {
display: none;
position: absolute;
left: 50px;
top: 200px;
}
.Login-Body {
overflow-x: hidden;
margin-left: -15px;
margin-right: -15px;
}
.Login-Input {
height: 55px;
border-radius: 20px;
}
.Login-Input-Btn {
height: 50px;
width: 150px;
border-radius: 10px;
}
.Form-Div {
margin: 0 50px 0 50px;
}