Build a Python Chat App with Django and React

Amos G.
Amos G.
Published June 13, 2019 Updated April 30, 2024
Header image

Building a real-time chat messaging application can be daunting and time-consuming for project and development teams. One reason is that the backend and frontend infrastructures must handle many aspects, like security and scalability. To build the Python app, we will use Stream's API for chat to handle WebSocket connections and other heavy lifting using Go, Raft, and RocksDB.

Prerequisites

To follow along and complete this tutorial, you should download and install the following technologies and tools on your Mac or Windows computer.

  • An IDE: You can follow this tutorial using any IDE. However, to edit the Python and Django files, you should preferably use VS Code or Pycharm.
  • Command line tool: For installing Python and other packages.
  • Python and Django: For handling user authentication and authorization.
  • Stream Chat React: An API for chat that uses Go, Raft, and - RocksDB to handle WebSocket connections and other heavy lifting.
  • Stream Dashboard: To provide an app secret and API key to be used later in this tutorial.

Get the Source Code

Find the codebase of this tutorial on GitHub and follow the few instructions in the repository to clone and install the sample project. Also, check out and make sure have all the requirements under the Prerequisites section, and let's start coding! 🤓.

Step 1: Create a Chat Demo UI

A preview of the chat demo UI

Before diving into the Django and Python chat, let's create a React frontend, so that we have something nice and visual to look at. Our demo chat app is shownin the above preview. Open any command line tool you prefer and enter the following commands.

shell
1
2
3
4
brew install node # skip if installed npm create vite@latest chat-frontend cd chat-frontend npm add stream-chat-react

To display the demo Reach chat UI, ensure you have installed the latest version of Node.js. As seen above, we initialize a new React project using Vite build tool npm create vite@latest chat-frontend. Then, in the folder the project generates, we install the Stream Chat SDK for React npm add stream-chat-react with NPM. You may also use yarn to initialize the project and install the chat SDK.

Launch the newly created project in an IDE like VS Code and replace the content App component App.tsx with the following sample code.

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// App.tsx import React from "react"; import { Chat, Channel, ChannelHeader, Thread, Window } from "stream-chat-react"; import { MessageList, MessageInput } from "stream-chat-react"; import { StreamChat } from "stream-chat"; import "stream-chat-react/dist/css/index.css"; const chatClient = new StreamChat("qk4nn7rpcn75"); // Demo Stream Key const userToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY29vbC1za3ktOSJ9.mhikC6HPqPKoCP4aHHfuH9dFgPQ2Fth5QoRAfolJjC4"; // Demo Stream Token chatClient.setUser( { id: "cool-sky-9", name: "Cool sky", image: "https://getstream.io/random_svg/?id=cool-sky-9&name=Cool+sky" }, userToken ); const channel = chatClient.channel("messaging", "godevs", { // image and name are required, however, you can add custom fields image: "https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png", name: "Talk about Go" }); const App = () => ( <Chat client={chatClient} theme={"messaging light"}> <Channel channel={channel}> <Window> <ChannelHeader /> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat> ); export default App;

To summarize the sample code, we import Stream's chat SDK, which we just installed, and its reusable chat components. Then, we create an instance of the SDK's chat client and initialize it with a hard-coded user token. The token must be generated from a server for a production web application. You can also use your Stream dashboard's API key to create a token using the Stream's token generator service for testing. Sign up for a free account to get started.

Next, we should start the development server to see our chat demo live in the browser. Open the integrated Terminal in VS Code. cd into the chat-frontend root folder and execute the following command to run the development server.

npm run dev

You will then see information like the one in the image below inside the Terminal window, along with a link to open the app with your local host.

Local host preview

Open the localhost’s http://localhost:5173/ to see a functional React messaging application supporting media upload, reactions, threads, replies, and more.

Step 2: Configure Python and Django

In this section, we will download and install Python and Django and set up a virtual environment to run the app. If you have already installed Python 3, you may skip the steps outlined below. Please note that if you are working on macOS, the operating system comes with a default installation of Python 2. We are not using this older version of Python in this tutorial. We should install Python 3 and set it up. First, check the version of Python on your machine with:

python --version # Windows
python3 --version # macOS

If Python 3 is not installed, you should download and install the latest version.

Create a Virtual Environment

The virtual environment and Django do not install along with the default Python installation. Therefore, we need to install them using pip, a dependency manager, and a package installer for Python. Let's use it to install a virtual environment for the app.

First, open your command line environment and enter the command:

pip install pipenv # Windows
pip3 install pipenv # macOS

Now, we should activate the Python 3 interpreter to use the app's virtual environment with the following; else, we will encounter an error when we run the app:

pipenv shell

Install Django

Let's cd into the project's root folder and install Django with:

pipenv install django

Initialize a New Django Project

Now that we have Django installed, we can create a new project using:

django-admin startproject mychat .

The command above will create a new directory and the Django project inside it.

Run the App in the Virtual Environment

To run the virtual environment, open a new Terminal window in VS Code or use your command line environment to run the following in the mychat folder:

python manage.py runserver

Alternatively, we can run the virtual environment with Django Admin django-admin runserver. Before running this command, ensure django-admin knows about the project settings.

Let's configure it in VS Code. First, we need to get the path of the virtual environment. The path can be obtained with:

pipenv --venv

The above command will give a path similar to:

/Users/amosgyamfi/.local/share/virtualenvs/mychat-2pHymnq_

Copy the path and go to VS Code. Select View -> Command Palette... and search for Python Interpreter. Add a new one and paste the path above. Now that django-admin knows about the project settings, go ahead and run the app using:

django-admin runserver

You will now see a preview similar to this one.

Step 3: Add User Authentication and Authorization

From the previous step, we have seen that our app is running successfully with Django. This section aims to authenticate and authorize a user against the Django backend. Let's follow the few steps here to create a user.

  1. Run python manage.py migrate to ask the Django backend to apply any pending database migrations.
  2. Create an admin or super user python manage.py createsuperuser. This step requires a username, email, and password. You can leave the username field blank to log in with the user name on your machine.
Super user account creation
  1. Keep the virtual environment running with python manage.py runserver.
  2. When you see the above message Superuser created successfully after running python manage.py createsuperuser, you can log in with this URL http://localhost:8000/admin/.
Django Admin UI

Voila! 👏. You should see the Django admin screen below.

Django admin screen

Step 4: Integrate React with Django

This section will integrate React with the Django project using a Django Rest Framework package. To make everything work successfully, we will need to create endpoints for:

  • User Signup
  • User Login

We could build those ourselves. However, a package called Djoser has already solved this problem. It configures the necessary API endpoints for user registration, login, password reset, etc.

Building your own app? Get early access to our Livestream or Video Calling API and launch in days!

To install Djoser, use the following snippet:

pip install djangorestframework djoser

If you get an error on macOS after running the command above, prepend sudo to the snippet.

Then, edit urls.py and change the file to contain:

python
1
2
3
4
5
6
7
8
9
// urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('auth/', include('djoser.urls')), path('auth/', include('djoser.urls.authtoken')), ]

Once complete, edit settings.py and make the following changes:

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', 'djoser', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', ) }

For more on the API endpoints that Djoser exposes, have a look at djoser sample usage.

Now, let’s go ahead and test the registration endpoint:

curl -X POST http://127.0.0.1:8000/auth/users/ --data 'username=djoser&password=alpine12'

You will get back the following result in the command line:

{"email":"","username":"djoser","id":2}%

Step 5: Generate Tokens To Access Stream's Chat Server

Now, we need to customize the Djoser views to generate tokens for Stream. Let's get started by organizing our files a bit to create a chat app folder in our project (make sure that you are in the correct directory):

shell
1
python manage.py startapp auth

Install Stream Chat

We now have a new Django app. So, we can use pip install stream-chat to add Stream Chat to the project.

After a successful installation, you will see a message similar to:

shell
1
Successfully installed aiodns-3.2.0 aiofile-3.8.8 aiohttp-3.9.5 aiosignal-1.3.1 attrs-23.2.0 caio-0.9.13 frozenlist-1.4.1 multidict-6.0.5 pycares-4.4.0 stream-chat-4.15.0 yarl-1.9.4

Create a Custom Serializer

Add a new Python file serializers.py in the auth folder with the following logic:

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// serializers.py from djoser.serializers import TokenSerializer from rest_framework import serializers from djoser.conf import settings as djoser_settings from stream_chat import StreamChat from django.conf import settings class StreamTokenSerializer(TokenSerializer): stream_token = serializers.SerializerMethodField() class Meta: model = djoser_settings.TOKEN_MODEL fields = ('auth_token','stream_token') def get_stream_token(self, obj): client = StreamChat(api_key=settings.STREAM_API_KEY, api_secret=settings.STREAM_API_SECRET) token = client.create_token(obj.user.id) return token

Update the settings.py file to use the custom serializer by adding the following:

python
1
2
3
4
5
6
7
STREAM_API_KEY = ‘YOUR_STREAM_API_KEY’ # https://getstream.io/dashboard/ STREAM_API_SECRET = ‘YOUR_STREAM_API_SECRET’ DJOSER = { 'SERIALIZERS': { 'token': 'auth.serializers.StreamTokenSerializer', } }

Create a new chat app in your Stream’s dashboard and copy your API key and the app’s secret to fill in the placeholders in the code snippet above, similar to this image.

API key and app secret

Apply any pending database migrations by running the following:

python manage.py migrate

Python migrate command status

To verify that it works, hit the login endpoint with a POST request:

curl -X POST http://127.0.0.1:8000/auth/token/login/ --data 'username=djoser&password=alpine12'

Running the command above returns the auth_token and stream_token fields.

Auth and Stream token

Note: If the curl snippet fails to return the auth_token and stream_token, quit the server, rerun it with python manage.py runserver, and try again.

Step 6: Integrate Auth

Adding an authentication later to the front end is essential for obvious reasons. In our case, it’s beneficial because we can fetch a user token from the backend API (powered by Python) and dynamically use it when sending messages.
First, install the Cross-Origin Resource Sharing (CORS) middleware package for Django to handle the server headers:

pip install django-cors-headers

Then, modify your settings.py to reference the djors-cors-header middleware:

python
1
2
3
4
5
6
7
8
9
10
11
12
13
//settings.py INSTALLED_APPS = ( ... 'corsheaders', ... ) MIDDLEWARE = [ ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ]

Still in the settings.py file, add the following:

CORS_ORIGIN_ALLOW_ALL = True

The above means any website can request the Django application, regardless of origin.

The next step requires a few modifications to the React front end. To start, you should ensure that you have all of the dependencies installed via yarn or npm:

npm add axios react-dom react-router-dom

  • Axios is an HTTP client for Node.js.
  • React Dom: A package serving as an entry point to the DOM and server renderers for React.
  • React Router Dom: Contains bindings for using React Router in web apps.

Next, create the following files within your src directory of the chat-frontend folder:

Then, update the content of the App.js or App.jsx file with the following sample code.

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*App.js*/ import React from "react"; import { BrowserRouter as Router, Switch } from "react-router-dom"; import Chat from "./Chat"; import Login from "./Login"; import UnauthedRoute from "./UnauthedRoute"; import AuthedRoute from "./AuthedRoute"; const App = () => ( <Router> <Switch> <UnauthedRoute path="/auth/login" component={Login} /> <AuthedRoute path="/" component={Chat} /> </Switch> </Router> ); export default App;

Be sure to replace YOUR_STREAM_APP_ID with a valid Stream App ID in the Chat.js file. The App ID can be found on the dashboard.
Restart your front-end application to hit the auth wall! Then, enter your email and password. A token will be requested and stored in local storage.

If you encounter a Switch error in your App.js, remove the react-router-dom package and install version 5.2.0.

shell
1
2
npm uninstall react-router-dom npm install react-router-dom@5.2.0

Step 7: Send a Message From the Python Chat Server

Occasionally, you will want to write to the chat API using your backend Python-based server. Here’s a quick management command that you can use:

Verify that the installed apps look like this in settings.py:

python
1
2
3
4
5
6
7
8
9
10
11
12
INSTALLED_APPS = [ 'corsheaders', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', 'djoser', ]

Next, create the directory chat/management/commands. In that directory, add a file called broadcast.py with this content.

You can now try posting a message to the chat like this:

python manage.py broadcast --message hello

And you should see a response like this:

Broadcast response

Final Thoughts

Hopefully, you enjoyed this tutorial on building a Python chat application!
For an interactive tour of Stream Chat, please have a look at our API Tutorial. Visit the React Components docs to learn more about the Chat SDK. Finally, we offer various SDKs for popular languages and frameworks if you want to build chat on top of Stream.

Integrating Video With Your App?
We've built a Video and Audio solution just for you. Check out our APIs and SDKs.
Learn more ->