上一篇: 带你进入异步Django+Vue的世界 - Didi打车实战(3)
后台数据模型设计
Demo: https://didi-taxi.herokuapp.com/
Django Channels
为了支持即时消息收发、群发群收、异步处理,我们对后台添加Channels。
- WebSockets
- Django Channels
安装Channels:
pip install channels channels-redis
修改配置文件:
- 添加
channels
APP - 添加
ASGI_APPLICATION
- 添加
CHANNEL_LAYERS
,使用Redis作为后台
# /backend/settings/dev.py
INSTALLED_APPS = [
'channels',
。。。
ASGI_APPLICATION = 'backend.routing.application'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'dist', 'media')
REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379')
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': { 'hosts': [REDIS_URL]},
}
}
- 创建ASGI application
运行django时,会切换到ASGI服务模式,同时处理HTTP和Websockets访问。
# /backend/asgi.py
import os
import django
from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings.dev')
django.setup()
application = get_default_application()
- 创建ASGI路由文件
前端以/ws/taxi/
地址来进行WebSockets请求。
# backend/routing.py
from django.urls import path
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from .api.consumers import TaxiConsumer
# changed
application = ProtocolTypeRouter({
'websocket': AuthMiddlewareStack(
URLRouter([
path('ws/taxi/', TaxiConsumer),
])
)
})
- 创建Consumer
Consumer是实现类似View的功能,处理WebSockets消息。
# api/consumers.py
from channels.generic.websocket import AsyncJsonWebsocketConsumer
class TaxiConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
user = self.scope['user']
if user.is_anonymous:
await self.close()
else:
await self.accept()
content = {
'type': 'from Django',
'data': "welcome, you're connected to Channels!"
}
await self.send_json(content)
拒绝非登录用户。对于已登录用户,则接收连接,并返回欢迎信息。
目录改动不少,当前结构为:
git/didi-project$ tree -I node_modules -L 3
.
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── Procfile
├── README.md
├── app.json
├── backend
│ ├── __init__.py
│ ├── api
│ │ ├── __init__.py
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── consumers.py
│ │ ├── migrations
│ │ ├── models.py
│ │ ├── serializers.py
│ │ ├── tests.py
│ │ ├── urls.py
│ │ └── views.py
│ ├── asgi.py
│ ├── routing.py
│ ├── settings
│ │ ├── __init__.py
│ │ ├── dev.py
│ │ └── prod.py
│ ├── urls.py
│ └── wsgi.py
├── db.sqlite3
├── dist
├── manage.py
├── package.json
├── public
│ ├── index.html
│ ├── manifest.json
│ ├── robots.txt
│ └── static
│ ├── favicon.ico
│ └── img
├── src
│ ├── App.vue
│ ├── assets
│ ├── components
│ ├── config.js
│ ├── main.js
│ ├── plugins
│ │ └── vuetify.js
│ ├── registerServiceWorker.js
│ ├── router.js
│ ├── services
│ │ ├── api.js
│ │ └── messageService.js
│ ├── store
│ │ ├── index.js
│ │ └── modules
│ │ │ └── messages.js
│ └── views
│ ├── Home.vue
│ ├── My404.vue
│ ├── Signin.vue
│ └── Signup.vue
├── vue.config.js
└── yarn.lock
运行ASGI
启动Redis服务:redis-server&
运行Django: python manage.py runserver
看到如下提示,就说明ASGI服务成功启动了:
(didi-project) git/didi-project$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
May 19, 2019 - 07:28:17
Django version 2.2.1, using settings 'backend.settings.dev'
Starting ASGI/Channels version 2.2.0 development server at http://127.0.0.1:8000/
验证一下,之前的HTTP登录、注册等功能一切正常。
前端添加WebSockets支持
直接写到