Last active
September 9, 2020 18:58
-
-
Save LinuxIsCool/126fe20a6fea98a4e3f4a265db5c33ac to your computer and use it in GitHub Desktop.
This fish scripts bootstraps the tutorial that can be found here: https://channels.readthedocs.io/en/latest/tutorial/part_1.html Virtualfish is used for the environment.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Name the environment, project and app | |
set -q ENVIRONMENT_NAME; or set ENVIRONMENT_NAME channels_tutorial | |
set -q PROJECT_NAME; or set PROJECT_NAME mysite | |
set -q APP_NAME; or set APP_NAME chat | |
# Initialize the environment | |
vf new $ENVIRONMENT_NAME | |
vf connect | |
pip install django channels django-redis channels-redis | |
# Initialize the project and the app | |
django-admin startproject $PROJECT_NAME | |
cd $PROJECT_NAME | |
python manage.py startapp $APP_NAME | |
rm $APP_NAME/{admin.py,apps.py,models.py,tests.py} | |
rm -rf $APP_NAME/migrations/ | |
# Tutorial Part 1: Basic Setup | |
function insert_app_in_settings -a app -a project -d "Use Python to insert our app in settings.py" | |
python -c " | |
with open('$project/settings.py', 'r') as f: | |
settings_py = f.read() | |
settings_with_app = settings_py.replace('INSTALLED_APPS = [\n', 'INSTALLED_APPS = [\n\t\t\'$app\',\n') | |
with open('$project/settings.py', 'w') as f: | |
f.write(settings_with_app)" | |
echo "$app added to INSTALLED_APPS" | |
end | |
function insert_template -a app -d "Insert the default template" | |
set template_dir "$app/templates/$app" | |
mkdir -p $template_dir | |
echo "<!DOCTYPE html> | |
<!-- $app/templates/$app/index.html --> | |
<html> | |
<head> | |
<meta charset="utf-8"/> | |
<title>Chat Rooms</title> | |
</head> | |
<body> | |
What chat room would you like to enter?<br> | |
<input id="room-name-input" type="text" size="100"><br> | |
<input id="room-name-submit" type="button" value="Enter"> | |
<script> | |
document.querySelector('#room-name-input').focus(); | |
document.querySelector('#room-name-input').onkeyup = function(e) { | |
if (e.keyCode === 13) { // enter, return | |
document.querySelector('#room-name-submit').click(); | |
} | |
}; | |
document.querySelector('#room-name-submit').onclick = function(e) { | |
var roomName = document.querySelector('#room-name-input').value; | |
window.location.pathname = '/chat/' + roomName + '/'; | |
}; | |
</script> | |
</body> | |
</html>" > "$template_dir/index.html" | |
end | |
function insert_view -a app -d "Insert the default view" | |
set views_file "$app/views.py" | |
echo " | |
# chat/views.py | |
from django.shortcuts import render | |
def index(request): | |
return render(request, 'chat/index.html')" > $views_file | |
end | |
function insert_urls -a app -a project -d "Insert the default urls" | |
set app_urls_file "$app/urls.py" | |
echo " | |
# $app/urls.py | |
from django.urls import path | |
from . import views | |
urlpatterns = [ | |
path('', views.index, name='index'), | |
]" > $app_urls_file | |
set root_urls_file "$project/urls.py" | |
echo " | |
# $project/urls.py | |
from django.conf.urls import include | |
from django.urls import path | |
from django.contrib import admin | |
urlpatterns = [ | |
path('$app/', include('$app.urls')), | |
path('admin/', admin.site.urls), | |
]" > $root_urls_file | |
end | |
function insert_routing -a app -a project -d "Insert the default routing protocol" | |
set routing_file "$project/routing.py" | |
echo " | |
# mysite/routing.py | |
from channels.auth import AuthMiddlewareStack | |
from channels.routing import ProtocolTypeRouter, URLRouter | |
import chat.routing | |
application = ProtocolTypeRouter({ | |
# (http->django views is added by default) | |
'websocket': AuthMiddlewareStack( | |
URLRouter( | |
chat.routing.websocket_urlpatterns | |
) | |
), | |
}) | |
" > $routing_file | |
end | |
# Tutorial Part 1: Basic Setup | |
insert_app_in_settings $APP_NAME $PROJECT_NAME | |
insert_template $APP_NAME | |
insert_view $APP_NAME | |
insert_urls $APP_NAME $PROJECT_NAME | |
insert_routing $APP_NAME $PROJECT_NAME | |
insert_app_in_settings channels $PROJECT_NAME | |
echo " | |
ASGI_APPLICATION = '$PROJECT_NAME.routing.application' | |
CHANNEL_LAYERS = { | |
'default': { | |
'BACKEND': 'channels_redis.core.RedisChannelLayer', | |
'CONFIG': { | |
'hosts': [('127.0.0.1', 6379)], | |
}, | |
}, | |
} | |
" >> $PROJECT_NAME/settings.py | |
function insert_chat_room_template -a app -d "Insert the chat room template" | |
set template_dir "$app/templates/$app" | |
echo """ | |
<!DOCTYPE html> | |
<!-- chat/templates/chat/room.html --> | |
<html> | |
<head> | |
<meta charset='utf-8'/> | |
<title>Chat Room</title> | |
</head> | |
<body> | |
<textarea id='chat-log' cols='100' rows='20'></textarea><br> | |
<input id='chat-message-input' type='text' size='100'><br> | |
<input id='chat-message-submit' type='button' value='Send'> | |
{{ room_name|json_script:'room-name' }} | |
<script> | |
const roomName = JSON.parse(document.getElementById('room-name').textContent); | |
const chatSocket = new WebSocket( | |
'ws://' | |
+ window.location.host | |
+ '/ws/chat/' | |
+ roomName | |
+ '/' | |
); | |
chatSocket.onmessage = function(e) { | |
const data = JSON.parse(e.data); | |
document.querySelector('#chat-log').value += (data.message + '\n'); | |
}; | |
chatSocket.onclose = function(e) { | |
console.error('Chat socket closed unexpectedly'); | |
}; | |
document.querySelector('#chat-message-input').focus(); | |
document.querySelector('#chat-message-input').onkeyup = function(e) { | |
if (e.keyCode === 13) { // enter, return | |
document.querySelector('#chat-message-submit').click(); | |
} | |
}; | |
document.querySelector('#chat-message-submit').onclick = function(e) { | |
const messageInputDom = document.querySelector('#chat-message-input'); | |
const message = messageInputDom.value; | |
chatSocket.send(JSON.stringify({ | |
'message': message | |
})); | |
messageInputDom.value = ''; | |
}; | |
</script> | |
</body> | |
</html> | |
""" > "$template_dir/room.html" | |
end | |
function insert_urlpattern -a app -a urlpattern -d "Use Python to insert a url pattern in our app." | |
python -c " | |
with open('$app/urls.py', 'r') as f: | |
urls_py = f.read() | |
urls_py = urls_py.replace('urlpatterns = [\n', 'urlpatterns = [\n\t\t$urlpattern\n') | |
with open('$app/urls.py', 'w') as f: | |
f.write(urls_py)" | |
echo "urlpattern added to $app app." | |
end | |
function insert_consumer -a app -d "Create the default consumer." | |
set consumer_file "$app/consumers.py" | |
echo " | |
# chat/consumers.py | |
import json | |
from asgiref.sync import async_to_sync | |
from channels.generic.websocket import WebsocketConsumer | |
class ChatConsumer(WebsocketConsumer): | |
def connect(self): | |
self.room_name = self.scope['url_route']['kwargs']['room_name'] | |
self.room_group_name = 'chat_%s' % self.room_name | |
# Join room group | |
async_to_sync(self.channel_layer.group_add)( | |
self.room_group_name, | |
self.channel_name | |
) | |
self.accept() | |
def disconnect(self, close_code): | |
# Leave room group | |
async_to_sync(self.channel_layer.group_discard)( | |
self.room_group_name, | |
self.channel_name | |
) | |
# Receive message from WebSocket | |
def receive(self, text_data): | |
text_data_json = json.loads(text_data) | |
message = text_data_json['message'] | |
# Send message to room group | |
async_to_sync(self.channel_layer.group_send)( | |
self.room_group_name, | |
{ | |
'type': 'chat_message', | |
'message': message | |
} | |
) | |
# Receive message from room group | |
def chat_message(self, event): | |
message = event['message'] | |
# Send message to WebSocket | |
self.send(text_data=json.dumps({ | |
'message': message | |
}))" > $consumer_file | |
end | |
function insert_app_routing -a app -d "Create the default websocket router." | |
set routing_file "$app/routing.py" | |
echo " | |
# chat/routing.py | |
from django.urls import re_path | |
from . import consumers | |
websocket_urlpatterns = [ | |
re_path(r'ws/chat/(?P<room_name>\w+)/\$', consumers.ChatConsumer), | |
]" > $routing_file | |
end | |
# Tutorial Part 2: Implement a Chat Server | |
insert_chat_room_template $APP_NAME | |
echo """ | |
def room(request, room_name): | |
return render(request, 'chat/room.html', { | |
'room_name': room_name | |
}) | |
""" >> $APP_NAME/views.py | |
insert_urlpattern $APP_NAME "path(\'<str:room_name>/\', views.room, name=\'room\')," | |
insert_consumer $APP_NAME | |
insert_app_routing $APP_NAME | |
python manage.py migrate | |
python manage.py runserver 8000 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just make a new directory and run this fish script. You can set app_name, project_name and environment name like so: