├── example
├── apps
│ ├── __init__.py
│ ├── web
│ │ ├── __init__.py
│ │ ├── migrations
│ │ │ └── __init__.py
│ │ ├── models.py
│ │ ├── tests.py
│ │ ├── admin.py
│ │ └── views.py
│ └── websocket
│ │ ├── __init__.py
│ │ ├── migrations
│ │ └── __init__.py
│ │ ├── models.py
│ │ ├── tests.py
│ │ ├── admin.py
│ │ └── views.py
├── example
│ ├── __init__.py
│ ├── wsgi_websocket.py
│ ├── wsgi.py
│ ├── urls.py
│ └── settings.py
├── redis_sessions
│ ├── __init__.py
│ ├── settings.py
│ └── session.py
├── uwsgi-config
│ ├── uwsgi.ini
│ └── vassals
│ │ ├── web-uwsgi.ini
│ │ └── websocket-uwsgi.ini
├── manage.py
├── templates
│ ├── login.html
│ └── chat.html
└── nginx.conf
├── djangowebsocket
├── __init__.py
├── wsgi.py
└── view.py
├── setup.py
├── .gitignore
└── README.md
/example/apps/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/apps/web/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/example/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/apps/websocket/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/apps/web/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/apps/websocket/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/redis_sessions/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = '0.4.0'
2 |
--------------------------------------------------------------------------------
/example/apps/web/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/example/apps/web/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/example/apps/web/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/example/apps/websocket/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/example/apps/websocket/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/example/apps/websocket/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/example/uwsgi-config/uwsgi.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | chdir = %d
3 | master = true
4 | emperor = vassals
5 | vassal-set = pythonpath=../
6 |
7 |
--------------------------------------------------------------------------------
/djangowebsocket/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | __author__ = 'Wang Chao'
4 | __date__ = '15-1-9'
5 |
6 | version_info = (0, 1, 0)
7 | __version__ = VERSION = '.'.join(map(str, version_info))
8 |
--------------------------------------------------------------------------------
/example/uwsgi-config/vassals/web-uwsgi.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | chdir = %d../../
3 | env = DJANGO_SETTINGS_MODULE=example.settings
4 | module = example.wsgi:application
5 | socket = 127.0.0.1:7000
6 | master = true
7 | processes = 1
8 | enable-threads = true
9 |
10 |
--------------------------------------------------------------------------------
/example/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
7 |
8 | from django.core.management import execute_from_command_line
9 |
10 | execute_from_command_line(sys.argv)
11 |
--------------------------------------------------------------------------------
/example/uwsgi-config/vassals/websocket-uwsgi.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | chdir = %d../../
3 | env = DJANGO_SETTINGS_MODULE=example.settings
4 | module = example.wsgi_websocket:application
5 | http-socket = 127.0.0.1:7001
6 | master = true
7 | processes = 1
8 | enable-threads = true
9 |
10 | gevent = 1000
11 |
12 |
--------------------------------------------------------------------------------
/example/example/wsgi_websocket.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | __author__ = 'Wang Chao'
4 | __date__ = '15-1-23'
5 |
6 | import os
7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
8 |
9 | from djangowebsocket.wsgi import get_wsgi_application
10 | application = get_wsgi_application()
11 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from distutils.core import setup
2 |
3 | setup(
4 | name='djangowebsocket',
5 | version='0.0.1',
6 | packages=[''],
7 | url='https://github.com/yueyoum/djangowebsocket',
8 | license='',
9 | author='Yueyoum',
10 | author_email='yueyoum@gmail.com',
11 | description=''
12 | )
13 |
--------------------------------------------------------------------------------
/example/example/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for example project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
12 |
13 | from django.core.wsgi import get_wsgi_application
14 | application = get_wsgi_application()
15 |
--------------------------------------------------------------------------------
/example/example/urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import include, url
2 | from django.contrib import admin
3 |
4 | import apps.web.views
5 | import apps.websocket.views
6 |
7 |
8 | urlpatterns = [
9 | # Examples:
10 | # url(r'^$', 'example.views.home', name='home'),
11 | # url(r'^blog/', include('blog.urls')),
12 |
13 | # url(r'^admin/', include(admin.site.urls)),
14 |
15 | url(r'^$', apps.web.views.Index.as_view()),
16 | url(r'^ws/$', apps.websocket.views.Chat.as_view()),
17 | ]
18 |
--------------------------------------------------------------------------------
/djangowebsocket/wsgi.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | __author__ = 'Wang Chao'
4 | __date__ = '15-1-9'
5 |
6 | import gevent.monkey
7 | gevent.monkey.patch_all()
8 |
9 | import uwsgi
10 |
11 | import django
12 | from django.core.handlers.wsgi import WSGIHandler
13 |
14 | class WebSocketApplication(WSGIHandler):
15 | def _fake_start_response(self, *args, **kwargs):
16 | pass
17 |
18 | def __call__(self, environ, start_response):
19 | uwsgi.websocket_handshake()
20 | return super(WebSocketApplication, self).__call__(environ, self._fake_start_response)
21 |
22 |
23 | def get_wsgi_application():
24 | django.setup()
25 | return WebSocketApplication()
26 |
27 |
--------------------------------------------------------------------------------
/example/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DjangoWebsocket Demo. Login
6 |
7 |
8 |
13 |
14 |
15 |
16 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/example/redis_sessions/settings.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 |
3 |
4 | SESSION_REDIS_HOST = getattr(settings, 'SESSION_REDIS_HOST', 'localhost')
5 | SESSION_REDIS_PORT = getattr(settings, 'SESSION_REDIS_PORT', 6379)
6 | SESSION_REDIS_DB = getattr(settings, 'SESSION_REDIS_DB', 0)
7 | SESSION_REDIS_PREFIX = getattr(settings, 'SESSION_REDIS_PREFIX', '')
8 | SESSION_REDIS_PASSWORD = getattr(settings, 'SESSION_REDIS_PASSWORD', None)
9 | SESSION_REDIS_UNIX_DOMAIN_SOCKET_PATH = getattr(
10 | settings, 'SESSION_REDIS_UNIX_DOMAIN_SOCKET_PATH', None
11 | )
12 | SESSION_REDIS_URL = getattr(settings, 'SESSION_REDIS_URL', None)
13 |
14 | # should be on the format [(host, port), (host, port), (host, port)]
15 | SESSION_REDIS_SENTINEL_LIST = getattr(
16 | settings, 'SESSION_REDIS_SENTINEL_LIST', None
17 | )
18 | SESSION_REDIS_SENTINEL_MASTER_ALIAS = getattr(
19 | settings, 'SESSION_REDIS_SENTINEL_MASTER_ALIAS', None
20 | )
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 |
3 | ### Python template
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 |
8 | # C extensions
9 | *.so
10 | .idea
11 | # Distribution / packaging
12 | .Python
13 | env/
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 |
46 | # Translations
47 | *.mo
48 | *.pot
49 |
50 | # Django stuff:
51 | *.log
52 |
53 | # Sphinx documentation
54 | docs/_build/
55 |
56 | # PyBuilder
57 | target/
58 |
59 |
60 |
--------------------------------------------------------------------------------
/example/nginx.conf:
--------------------------------------------------------------------------------
1 |
2 | # add following settings in http scope!
3 | # map $http_upgrade $connection_upgrade {
4 | # default upgrade;
5 | # '' close;
6 | # }
7 |
8 |
9 |
10 | upstream web {
11 | server 127.0.0.1:7000;
12 | }
13 |
14 | upstream websocket {
15 | server 127.0.0.1:7001;
16 | }
17 |
18 | server {
19 | listen 8111;
20 |
21 | access_log off;
22 | error_log off;
23 |
24 |
25 | location ~ ^/ws/ {
26 | proxy_pass http://websocket;
27 | proxy_http_version 1.1;
28 | proxy_set_header Upgrade $http_upgrade;
29 | proxy_set_header Connection "upgrade";
30 | }
31 |
32 | location / {
33 | uwsgi_pass web;
34 | include uwsgi_params;
35 | }
36 | }
--------------------------------------------------------------------------------
/example/apps/websocket/views.py:
--------------------------------------------------------------------------------
1 | #! -*- coding: utf-8 -*-
2 |
3 |
4 | import datetime
5 |
6 | from djangowebsocket.view import WebSocketView
7 |
8 | now = lambda : datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
9 | def log(text):
10 | print "{0}: {1}".format(now(), text)
11 |
12 |
13 | class Chat(WebSocketView):
14 | def on_connect(self):
15 | print "on connect"
16 |
17 | self.name = self.request.session['name'].encode('utf-8')
18 | client_amount = self.redis.incr('demo-client-amount')
19 | self.send("{0} {1} 人在线".format(now(), client_amount))
20 | self.publish_global("{0} {1} 上线了".format(now(), self.name))
21 |
22 | def on_websocket_data(self, data):
23 | print "websocket data:", data
24 | self.publish_global("{0} {1}: {2}".format(now(), self.name, data))
25 |
26 |
27 | def on_channel_data(self, data):
28 | print "channel data", data
29 | data = str(data['data'])
30 | self.send(data)
31 |
32 | def on_connection_lost(self):
33 | print "connection lost"
34 | self.redis.incr('demo-client-amount', -1)
35 | self.publish_global("{0} {1} 下线了".format(now(), self.name))
36 |
--------------------------------------------------------------------------------
/example/apps/web/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render_to_response
2 | from django.views.generic import View
3 | from django.http import HttpResponseRedirect
4 | from django import forms
5 |
6 | class LoginForm(forms.Form):
7 | name = forms.CharField(required=True, widget=forms.TextInput(attrs={'class': 'pure-input-1-1'}))
8 |
9 |
10 | class Index(View):
11 | def get(self, request):
12 | name = request.session.get('name', None)
13 | if not name:
14 | return render_to_response(
15 | 'login.html',
16 | {
17 | 'action': request.path,
18 | 'form': LoginForm().as_p()
19 | }
20 | )
21 |
22 | return render_to_response(
23 | 'chat.html',
24 | {
25 | 'websocket_url': 'ws://' + request.get_host()
26 | }
27 | )
28 |
29 | def post(self, request):
30 | form = LoginForm(request.POST)
31 | if not form.is_valid():
32 | return HttpResponseRedirect(request.path)
33 |
34 | name = form.cleaned_data['name']
35 | request.session['name'] = name
36 | return HttpResponseRedirect(request.path)
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DjangoWebsocket
2 |
3 | 在Django中使用Websocket
4 |
5 | 需要
6 |
7 | * uwsgi
8 | * gevent
9 | * redis
10 |
11 |
12 | #### 完善中...
13 |
14 |
15 | ## Usage
16 |
17 |
18 | #### wsgi
19 |
20 | 在项目目录中创建一个 `wsgi_websocket.py` 文件, 建议与 django自己的 `wsgi.py` 放在相同目录下
21 |
22 | 内容如下:
23 |
24 | ```python
25 | import os
26 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example.settings")
27 |
28 | from djangowebsocket.wsgi import get_wsgi_application
29 | application = get_wsgi_application()
30 |
31 | ```
32 |
33 | #### view
34 |
35 | view要继承 `djangowebsocket.view.WebSocketView`
36 |
37 | 并且实现四个方法
38 |
39 | 例子:
40 |
41 | ```python
42 |
43 | from djangowebsocket.view import WebSocketView
44 |
45 | class MyView(WebSocketView):
46 | def on_connect(self):
47 | # 客户端链接上来会调用的函数
48 | # 在这里做一些初始化工作
49 | #
50 | # 属性:
51 | # self.request django WSGIRequest
52 | # self.redis redis client
53 | # self.channel redis pubsub endpiont
54 | #
55 | # 方法:
56 | # self.send(text) 向客户端发送text数据
57 | # self.send_binary(binary) 向客户端发送binary数据
58 | # self.publish_global(text) 向所有链接的客户端广播数据
59 |
60 | def on_websocket_data(self, data):
61 | # 从client接收到的数据
62 |
63 | def on_channel_data(self, data):
64 | # 从 redis pubsub 中获取的数据
65 |
66 | def on_connection_lost(self):
67 | # 客户端断开链接
68 |
69 | ```
70 |
71 | #### urls
72 |
73 | 将 你的url 映射到 `myapp.views.MyView.as_view()`
74 |
75 |
76 | ## Example
77 | example 是一个聊天例子, 在这里可以测试: http://114.215.129.77:8111
78 |
79 |
80 |
81 | ## 注意
82 |
83 | uwsgi 跑在 gevent 的事件循环上,每个客户端链接跑在一个greenlet中,
84 | 所以当链接的客户端数量 大于 uwsgi 配置中的 processes * gevent 总数,新客户端就不能链接
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/example/templates/chat.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | DjangoWebsocet Chat Demo
7 |
8 |
9 |
10 |
11 |
61 |
62 |
79 |
80 |
81 |
82 |
83 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/djangowebsocket/view.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | __author__ = 'Wang Chao'
4 | __date__ = '15-1-9'
5 |
6 | import logging
7 |
8 | import uwsgi
9 | import redis
10 | from gevent import select
11 |
12 | from django.conf import settings
13 | from django.http import HttpResponse
14 | from django.utils.decorators import classonlymethod
15 |
16 |
17 | logger = logging.getLogger('django.websocket')
18 |
19 | def _get_setting(key, default_value):
20 | return getattr(settings, key, default_value)
21 |
22 | redis_client = redis.Redis(
23 | connection_pool=redis.ConnectionPool(
24 | host=_get_setting('WS_REDIS_HOST', '127.0.0.1'),
25 | port=_get_setting('WS_REDIS_PORT', 6379),
26 | db=_get_setting('WS_REDIS_DB', 0)
27 | )
28 | )
29 |
30 | REDIS_GLOBAL_CHANNEL = _get_setting('WS_REDIS_GLOBAL_CHANNEL', 'DJWS-CHANNEL')
31 | TIMEOUT = _get_setting('WS_WAIT_TIMEOUT', 10)
32 |
33 |
34 | class WebSocketView(object):
35 | class WebSocketError(Exception):
36 | pass
37 |
38 |
39 | def __init__(self, request, *args, **kwargs):
40 | self.request = request
41 | self.args = args
42 | self.kwargs = kwargs
43 | self.redis = redis_client
44 | self.channel = self.redis.pubsub()
45 | self.channel.subscribe(REDIS_GLOBAL_CHANNEL)
46 | self.on_connect()
47 |
48 |
49 | def publish_global(self, text):
50 | print "PUBLISH GLOBAL", text
51 | self.redis.publish(REDIS_GLOBAL_CHANNEL, text)
52 |
53 | def recv(self):
54 | try:
55 | data = uwsgi.websocket_recv_nb()
56 | if data:
57 | self.on_websocket_data(data)
58 | except:
59 | raise self.WebSocketError()
60 |
61 | def send(self, text):
62 | uwsgi.websocket_send(text)
63 |
64 | def send_binary(self, binary_data):
65 | uwsgi.websocket_send_binary(binary_data)
66 |
67 | def on_connect(self):
68 | raise NotImplementedError()
69 |
70 | def on_connection_lost(self):
71 | raise NotImplementedError()
72 |
73 | def on_websocket_data(self, data):
74 | raise NotImplementedError()
75 |
76 | def on_channel_data(self, data):
77 | raise NotImplementedError()
78 |
79 |
80 | def run(self):
81 | websocket_fd = uwsgi.connection_fd()
82 | channel_fd = self.channel.connection._sock.fileno()
83 |
84 | fds = [websocket_fd, channel_fd]
85 |
86 | try:
87 | while True:
88 | readable, _, _ = select.select(fds, [], [], TIMEOUT)
89 | if not readable:
90 | self.recv()
91 | continue
92 |
93 | self.recv()
94 | data = self.channel.get_message(ignore_subscribe_messages=True)
95 | if data:
96 | self.on_channel_data(data)
97 |
98 | except self.WebSocketError:
99 | return HttpResponse('ws ok')
100 | finally:
101 | self.channel.unsubscribe()
102 | self.on_connection_lost()
103 |
104 | @classonlymethod
105 | def as_view(cls):
106 | def wrapper(request, *args, **kwargs):
107 | self = cls(request, *args, **kwargs)
108 | return self.run()
109 | return wrapper
110 |
111 |
--------------------------------------------------------------------------------
/example/redis_sessions/session.py:
--------------------------------------------------------------------------------
1 | import redis
2 |
3 | try:
4 | from django.utils.encoding import force_unicode
5 | except ImportError: # Python 3.*
6 | from django.utils.encoding import force_text as force_unicode
7 | from django.contrib.sessions.backends.base import SessionBase, CreateError
8 | from redis_sessions import settings
9 |
10 |
11 | # Avoid new redis connection on each request
12 |
13 | if settings.SESSION_REDIS_SENTINEL_LIST is not None:
14 | from redis.sentinel import Sentinel
15 |
16 | redis_server = Sentinel(settings.SESSION_REDIS_SENTINEL_LIST, socket_timeout=0.1) \
17 | .master_for(settings.SESSION_REDIS_SENTINEL_MASTER_ALIAS, socket_timeout=0.1)
18 |
19 | elif settings.SESSION_REDIS_URL is not None:
20 |
21 | redis_server = redis.StrictRedis.from_url(settings.SESSION_REDIS_URL)
22 | elif settings.SESSION_REDIS_UNIX_DOMAIN_SOCKET_PATH is None:
23 |
24 | redis_server = redis.StrictRedis(
25 | host=settings.SESSION_REDIS_HOST,
26 | port=settings.SESSION_REDIS_PORT,
27 | db=settings.SESSION_REDIS_DB,
28 | password=settings.SESSION_REDIS_PASSWORD
29 | )
30 | else:
31 |
32 | redis_server = redis.StrictRedis(
33 | unix_socket_path=settings.SESSION_REDIS_UNIX_DOMAIN_SOCKET_PATH,
34 | db=settings.SESSION_REDIS_DB,
35 | password=settings.SESSION_REDIS_PASSWORD,
36 | )
37 |
38 |
39 | class SessionStore(SessionBase):
40 | """
41 | Implements Redis database session store.
42 | """
43 | def __init__(self, session_key=None):
44 | super(SessionStore, self).__init__(session_key)
45 |
46 | self.server = redis_server
47 |
48 | def load(self):
49 | try:
50 | session_data = self.server.get(
51 | self.get_real_stored_key(self._get_or_create_session_key())
52 | )
53 | return self.decode(force_unicode(session_data))
54 | except:
55 | self.create()
56 | return {}
57 |
58 | def exists(self, session_key):
59 | return self.server.exists(self.get_real_stored_key(session_key))
60 |
61 | def create(self):
62 | while True:
63 | self._session_key = self._get_new_session_key()
64 |
65 | try:
66 | self.save(must_create=True)
67 | except CreateError:
68 | continue
69 | self.modified = True
70 | return
71 |
72 | def save(self, must_create=False):
73 | if must_create and self.exists(self._get_or_create_session_key()):
74 | raise CreateError
75 | data = self.encode(self._get_session(no_load=must_create))
76 | if redis.VERSION[0] >= 2:
77 | self.server.setex(
78 | self.get_real_stored_key(self._get_or_create_session_key()),
79 | self.get_expiry_age(),
80 | data
81 | )
82 | else:
83 | self.server.set(
84 | self.get_real_stored_key(self._get_or_create_session_key()),
85 | data
86 | )
87 | self.server.expire(
88 | self.get_real_stored_key(self._get_or_create_session_key()),
89 | self.get_expiry_age()
90 | )
91 |
92 | def delete(self, session_key=None):
93 | if session_key is None:
94 | if self.session_key is None:
95 | return
96 | session_key = self.session_key
97 | try:
98 | self.server.delete(self.get_real_stored_key(session_key))
99 | except:
100 | pass
101 |
102 | def get_real_stored_key(self, session_key):
103 | """Return the real key name in redis storage
104 | @return string
105 | """
106 | prefix = settings.SESSION_REDIS_PREFIX
107 | if not prefix:
108 | return session_key
109 | return ':'.join([prefix, session_key])
110 |
--------------------------------------------------------------------------------
/example/example/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for example project.
3 |
4 | Generated by 'django-admin startproject' using Django 1.8a1.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/dev/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/dev/ref/settings/
11 | """
12 |
13 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
14 | import os
15 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16 |
17 |
18 | # Quick-start development settings - unsuitable for production
19 | # See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
20 |
21 | # SECURITY WARNING: keep the secret key used in production secret!
22 | SECRET_KEY = 'xp1g)+n^pf-_0nlr^%xatu2su$&ze6d**#!oaw1rw&*lm_mk&%'
23 |
24 | # SECURITY WARNING: don't run with debug turned on in production!
25 | DEBUG = True
26 |
27 | TEMPLATE_DEBUG = True
28 |
29 | ALLOWED_HOSTS = []
30 |
31 |
32 | # Application definition
33 |
34 | INSTALLED_APPS = (
35 | 'django.contrib.admin',
36 | 'django.contrib.auth',
37 | 'django.contrib.contenttypes',
38 | 'django.contrib.sessions',
39 | 'django.contrib.messages',
40 | 'django.contrib.staticfiles',
41 | 'apps.web',
42 | 'apps.websocket',
43 | )
44 |
45 | MIDDLEWARE_CLASSES = (
46 | 'django.contrib.sessions.middleware.SessionMiddleware',
47 | 'django.middleware.common.CommonMiddleware',
48 | # 'django.middleware.csrf.CsrfViewMiddleware',
49 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
50 | 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
51 | 'django.contrib.messages.middleware.MessageMiddleware',
52 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
53 | # 'django.middleware.security.SecurityMiddleware',
54 | )
55 |
56 | ROOT_URLCONF = 'example.urls'
57 |
58 | TEMPLATES = [
59 | {
60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
61 | 'DIRS': [os.path.join(BASE_DIR, 'templates'),],
62 | 'APP_DIRS': True,
63 | 'OPTIONS': {
64 | 'context_processors': [
65 | 'django.template.context_processors.debug',
66 | 'django.template.context_processors.request',
67 | 'django.contrib.auth.context_processors.auth',
68 | 'django.contrib.messages.context_processors.messages',
69 | ],
70 | },
71 | },
72 | ]
73 |
74 | WSGI_APPLICATION = 'example.wsgi.application'
75 |
76 |
77 | # Database
78 | # https://docs.djangoproject.com/en/dev/ref/settings/#databases
79 |
80 | DATABASES = {
81 | 'default': {
82 | 'ENGINE': 'django.db.backends.sqlite3',
83 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
84 | }
85 | }
86 |
87 |
88 | # Internationalization
89 | # https://docs.djangoproject.com/en/dev/topics/i18n/
90 |
91 | LANGUAGE_CODE = 'en-us'
92 |
93 | TIME_ZONE = 'UTC'
94 |
95 | USE_I18N = True
96 |
97 | USE_L10N = True
98 |
99 | USE_TZ = True
100 |
101 |
102 | # Static files (CSS, JavaScript, Images)
103 | # https://docs.djangoproject.com/en/dev/howto/static-files/
104 |
105 | STATIC_URL = '/static/'
106 |
107 |
108 | LOGGING = {
109 | 'version': 1,
110 | 'formatters': {
111 | 'verbose': {
112 | 'format': '%(levelname)s %(asctime)s %(message)s'
113 | },
114 | },
115 | 'handlers': {
116 | 'console': {
117 | 'class': 'logging.StreamHandler',
118 | 'level': 'DEBUG',
119 | 'formatter': 'verbose',
120 | }
121 | },
122 | 'loggers': {
123 | 'django.request': {
124 | 'handlers': ['console'],
125 | 'level': 'ERROR',
126 | 'propagate': True,
127 | }
128 | }
129 | }
130 |
131 |
132 |
133 |
134 |
135 |
136 | # redis session
137 | SESSION_ENGINE = 'redis_sessions.session'
138 | SESSION_REDIS_HOST = '127.0.0.1'
139 | SESSION_REDIS_PORT = 6379
140 | SESSION_REDIS_DB = 0
141 |
142 | SESSION_COOKIE_AGE = 60
143 |
144 | # websocket
145 | WS_REDIS_HOST = '127.0.0.1'
146 | WS_REDIS_PORT = 6379
147 | WS_REDIS_DB = 0
148 | WS_REDIS_GLOBAL_CHANNEL = 'my_test_channel'
149 | WS_WAIT_TIMEOUT = 10 # seconds
150 |
--------------------------------------------------------------------------------