Python Telegram bot with Django Framework

Python Telegram bot with Django Framework

Valerii Pavlikov


Hey everyone!

I’ve decided to create a telegram bot using Django. It’s not the usual way but I thought “why not” and created it. It’s not a deep-learning guide, I just want to answer for most important questions which I faced during development.

So this guide answers next questions:

  1. How to raise up Django project and configure it for working with Telegram?
  2. How to work locally?
  3. How to deploy it?

Stack

Pre-prepared steps

You need to do some steps before this guide:

  • Create Telegram bot using BotFather
  • Deploy a standard Django project locally


Configure Django project with python-telegram-bot library

Installation

We are going to use python-telegram-bot v13.x. It’s very important to see library has two different versions. What is the difference? You can use async starting from v20.x and you can’t before this version. Despite the fact that Django since version 4 supports working with async — in this case, we will work without async.

So you need to install the library for your Django project.

pip install python-telegram-bot~=13.14

Let’s create a new application called bot and we will conduct all our development there.


We’re going to use an example which is provided by python-telegram-bot library. This is an example of working with conversation.

conversation bot

Let’s create a new file in bot application called handlers.py and put the code from an example there.

Webhooks

We’re going to use webhook in our application because we’re working with Django and need some URL which sends to us any update from Telegram.

To get more information about webhooks you can find it here.

We will use an alternative solution that is proposed from the documentation — without using threads.

So the most important point in our case is to configure work with the Dispatcher. In order to do this, we will create a new file in botapplication called tg_init.py .

from django.conf import settings
from telegram import Bot
from telegram.ext import Dispatcher

from bot.handlers import conv_handler


def telegram_bot():
    bot = Bot(settings.BOT_TOKEN)
    return bot


def telegram_dispatcher():
    bot = telegram_bot()
    dispatcher = Dispatcher(bot, None, workers=0)

    # Register handlers here
    dispatcher.add_handler(conv_handler)

    return dispatcher


BOT = telegram_bot()
DISPATCHER = telegram_dispatcher()


After we have set up work with Dispatcher, we need to create a controller that will be our webhook and to which updates will come from Telegram. Let’s go to views.py file and do it there.

import json

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from telegram import Update

from bot.tg_init import BOT, DISPATCHER


@csrf_exempt
def process(request):
    data = json.loads(request.body.decode())
    update = Update.de_json(data, BOT)
    DISPATCHER.process_update(update)

    return JsonResponse({})

It’s essential to add @csrf_exempt because we can’t control here CSRF protection and it won’t work without this decorator.


When we did the configuration of code for working with Telegram bot, we will need to set our webhook. First of all, we have to add URL to urls.py file.

from django.contrib import admin
from django.urls import path

from bot.views import process

urlpatterns = [
    path("admin/", admin.site.urls),
    path("process/", process, name="process"),
]


And finally, we need to set up webhook (make it clear to the Telegram API where to send updates). To do this, we will create a django management command. Of course, we could set up webhook through shell but using command is easier to work with in perspective. In any case, it’s up to you.

bot/
  management/
    commands/
      set_webhook.py


from django.conf import settings
from django.core.management.base import BaseCommand
from django.urls import reverse

from bot.tg_init import BOT


class Command(BaseCommand):

    def handle(self, *args, **options):
        url = "{}{}".format(settings.SERVER_DOMAIN, reverse("process"))
        is_appointed = BOT.set_webhook(url=url)
        if is_appointed:
            self.stdout.write(self.style.SUCCESS("Webhook was successfully appointed."))
        else:
            self.stdout.write(self.style.ERROR("Something went wrong."))

Ngrok

Since Telegram API only works with certified domains, we cannot use our standard domain locally http://127.0.0.1:8000 . We need something that provides https and ngrok will help us with that.

Do the installation and run it. We need to copy the URL address with https .

So add this URL to settings.py in SERVER_DOMAIN var and after that run django management command.

./manage.py set_webhook

Congrats! You can run your Telegram bot and check how it works!

Deploy Django project to production

I will not tell the whole process of deployment, delving into all aspects of nginx, gunicorn and so on. In this block, I will focus only on what will help you successfully launch the bot in production.

I use this guide for deploying Django project — so do it all step by step. If you didn't deploy before, firstly you could try to deploy just a simple Django project (without Telegram settings).

How To Set Up Django with Postgres, Nginx, and Gunicorn on Ubuntu 22.04

So, the most important thing during deploying Django project with Telegram settings is to make the correct configuration gunicorn.service file.

Please note that you need to install only a single worker instead of a multiplay.

gunicorn.service

Also after deploying don’t forget to change SERVER_NAME to real production domain and run set_webhook command.

Conclusion

It’s my first experience with writing articles and guides but I hope it was helpful for you! If you found any mistakes please let me gently know.

Useful links and the resources used


Report Page