Getting Started With Django Channels - A Simple Chat App Part 1
Tags: python, django, webdev, beginners
Published: 2021-09-23 08:21:00

In my last [article](https://dev.to/earthcomfy/introduction-to-web-sockets-3n7m) I talked about WebSockets and how we can establish a web socket connection from the client side/JavaScript. Today, we will begin our journey to write a simple chat app, which will be really helpful in demonstrating how web sockets work and how we can build real-time Django apps.

-----

As we already know, in a typical Django project the client makes an HTTP request, Django calls the view that is responsible for managing this request and returns a response back to the client. 

This communication is pretty standard. But ever since Django has introduced ASGI and started supporting it natively, we are able to write Django applications with asynchronous code in addition to synchronous code. *Django Channels* which let's us work with web sockets is also built on ASGI.

---------

Before getting any further, let's talk about ASGI and its predecessor WSGI.

> [WSGI](https://wsgi.readthedocs.io/en/latest/what.html) - WSGI is the Web Server Gateway Interface. It is a specification that describes how a web server communicates with web applications, and how web applications can be chained together to process one request. It's like a mediator for carrying out interaction between a web server and a python application.

> [ASGI](https://asgi.readthedocs.io/en/latest/) - ASGI (Asynchronous Server Gateway Interface) is a spiritual successor to WSGI, intended to provide a standard interface between async-capable Python web servers, frameworks, and applications.

So, the difference is that WSGI provides a standard for running synchronous apps while ASGI let us run asynchronous apps allowing us to work with more advanced protocols like web sockets where it can send and receive multiple data over a single connection.

If ASGI is enabled in our app, Django will let us write asynchronous views, and manage async enabled requests. But to write async applications that work with WebSockets, we need to use Django Channels.

If you haven't already, check out my last article on [WebSockets](https://dev.to/earthcomfy/introduction-to-web-sockets-3n7m) before continuing.

----

### Django Channels
Django channels goes beyond HTTP and support other protocols such as web sockets and is built on ASGI. 

The underlying implementations we are going to see in channels are pretty much similar to the regular HTTP views that we are used to working with. In order to handle a WebSocket connection, channels has *routing.py* and *consumers.py*.

- *routing.py* is like *urls.py*
- *consumers.py* is like *views.py*

> When a request or new socket comes in, Channels will follow its routing table, then find the right consumer for that incoming connection, and start up a copy of it. More on this later.

------

### Set up and Installation

1) Set up a virtual environment
2) Install Django then create a project
```
pip install django
django-admin startproject config .
```
3) Install channels
```
pip install channels
```
4) Add channels to your list of installed apps in the settings.

settings.py
```python
INSTALLED_APPS = [
    # ...
    'channels',
]
```
5) Go to your project's *asgi.py* file and adjust it as follows to wrap the Django ASGI application:

asgi.py
```python
import os

import django
from channels.http import AsgiHandler
from channels.routing import ProtocolTypeRouter

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
django.setup()

application = ProtocolTypeRouter({
  "http": AsgiHandler(),
  # We will add WebSocket protocol later, but for now it's just HTTP.
})
```

6) And finally, set your ASGI_APPLICATION setting to point to that routing object as your root application:

settings.py
```python
ASGI_APPLICATION = "config.asgi.application"
```

Perfect! Now channels has taken over the runserver command and an ASGI/Channels development server will be run from this point forward.

Check this by running the development server `python manage.py runserver` and you will see the following:

![development server](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cyq7bgey8bhhqjgp1rqg.png)


-----------

### Getting started
The best way to get started with channels and ASGI is by creating a simple chat app. Therefore, after you are done with the basic set up and installation, go ahead and create a Django app.

```
python manage.py startapp chat
```

Add it to the list of installed apps in your settings.

settings.py
```python
INSTALLED_APPS = [
    # ...
    'chat',
]
```

Alright, for this simple chat app we are going to have 2 views.

- The first view we are going to create is the **index** view. This is what allows users to type in the chat room they want to join.
- The second view is the **room** view that lets users in the same connection to see messages posted in that chat room.

In this tutorial, we will create the first view which is the **index** view.

That being said, let's head over to our chat app and create a templates directory. Within the templates directory, create another directory named **chat**, and within that create a file named *index.html*.

Put the following code inside the *index.html* fle.

index.html
```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</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>
```
- The script in the above html file is pretty straight forward. It's going to listen to events i.e. when the user presses enter or the submit button after typing in the chat room, he/she will be redirected to the room view http://127.0.0.1:8000/chat/roomName/. 


Now, let's create the view that is associated with the above template.

views.py
```python
from django.shortcuts import render

def index(request):
    return render(request, 'chat/index.html')
```


Now, Create *urls.py* module inside the chat app and map the `index` view to the url patterns.

chat/urls.py
```python
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
```

- Go to the project's *urls.py* file and include the chat app's url.

config/urls.py
```python
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('chat/', include('chat.urls')),
]
```

### Time to check if it's working

```
python manage.py runserver
```

Go to http://127.0.0.1:8000/chat/ in your browser and voila you have the index page. Type in a chat room and you will get redirected to the room view which we haven't created yet so it'll display a “Page not found” error page.
 

![Well Done!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/arlkd1nv5d1yvs1jhmsn.gif)

*Reference - https://channels.readthedocs.io/en/stable/*

That's it for today. In an upcoming tutorial we will create the room view and start writing consumers.