Ошибка Django received a naive datetime (2024-06-01 00:00:00) while time zone support is active

Запускаю в django telegram бот, после того как пишу /statistic в бот выходит эта ошибка:

D:\projects\neotelecom-master\venv\Lib\site-packages\django\db\models\fields\__init__.py:1366: RuntimeWarning: DateTimeField JoinUs.created_at received a naive datetime (2024-06-01 00:00:00) while time zone support is active.
  warnings.warn("DateTimeField %s.%s received a naive datetime "
D:\projects\neotelecom-master\venv\Lib\site-packages\django\db\models\fields\__init__.py:1424: RuntimeWarning: DateTimeField JoinUs.created_at received a naive datetime (2024-06-07 14:01:50.475535) while time zone support is active.
  warnings.warn("DateTimeField %s received a naive datetime (%s)"
D:\projects\neotelecom-master\venv\Lib\site-packages\django\db\models\fields\__init__.py:1366: RuntimeWarning: DateTimeField CallMe.created_at received a naive datetime (2024-06-01 00:00:00) while time zone support is active.
  warnings.warn("DateTimeField %s.%s received a naive datetime "
D:\projects\neotelecom-master\venv\Lib\site-packages\django\db\models\fields\__init__.py:1424: RuntimeWarning: DateTimeField CallMe.created_at received a naive datetime (2024-06-07 14:01:50.475535) while time zone support is active.
  warnings.warn("DateTimeField %s received a naive datetime (%s)"
2024-06-07 14:01:53,787 (util.py:65 WorkerThread2) ERROR - TeleBot: "ApiException occurred, args=('A request to the Telegram API was unsuccessful. The server returned HTTP 400 Bad Request. Response body:\n[b\'{"ok":false,"error_code":400,"description":"Bad Request: can\\\'t parse entities: Can\\\'t find end of the entity starting at byte offset 186"}\']',)
Traceback (most recent call last):
  File "D:\projects\neotelecom-master\venv\Lib\site-packages\telebot\util.py", line 59, in run
    task(*args, **kwargs)
  File "D:\projects\neotelecom-master\core\applications\tbot\bot_core.py", line 42, in repeat_all_messages
    t_bot.send_message(message.chat.id, text, parse_mode='markdown')
  File "D:\projects\neotelecom-master\venv\Lib\site-packages\telebot\__init__.py", line 597, in send_message
    apihelper.send_message(self.token, chat_id, text, disable_web_page_preview, reply_to_message_id,
  File "D:\projects\neotelecom-master\venv\Lib\site-packages\telebot\apihelper.py", line 140, in send_message
    return _make_request(token, method_url, params=payload, method='post')
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\projects\neotelecom-master\venv\Lib\site-packages\telebot\apihelper.py", line 56, in _make_request
    return _check_result(method_name, result)['result']
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\projects\neotelecom-master\venv\Lib\site-packages\telebot\apihelper.py", line 75, in _check_result
    raise ApiException(msg, method_name, result)
telebot.apihelper.ApiException: A request to the Telegram API was unsuccessful. The server returned HTTP 400 Bad Request. Response body:
[b'{"ok":false,"error_code":400,"description":"Bad Request: can\'t parse entities: Can\'t find end of the entity starting at byte offset 186"}']    
"
2024-06-07 14:01:53,788 (__init__.py:417 MainThread) ERROR - TeleBot: "A request to the Telegram API was unsuccessful. The server returned HTTP 400 Bad Request. Response body:
[b'{"ok":false,"error_code":400,"description":"Bad Request: can\'t parse entities: Can\'t find end of the entity starting at byte offset 186"}']"

applications/tbot/bot_core.py:

import datetime
import telebot
import pytz

from applications.core.models import JoinUs, CallMe
from project import settings

t_bot = telebot.TeleBot(settings.BOT_API_KEY)


def _get_users_list(obj):
    users = {}
    for item in obj:
        if item.user in users.keys():
            users[item.user] += 1
            continue
        users[item.user] = 1

    join_us_users = ''
    for user in users:
        join_us_users += f" \n{user}  -  {users[user] }"

    return join_us_users


@t_bot.message_handler(commands=["statistic"])
def repeat_all_messages(message):
    first_day = datetime.date.today().replace(day=1)
    current_time = datetime.datetime.now()

    join_us = JoinUs.objects.filter(status='accepted', created_at__gte=first_day, created_at__lte=current_time).all()
    join_us_users = _get_users_list(join_us)

    call_me = CallMe.objects.filter(status='accepted', created_at__gte=first_day, created_at__lte=current_time).all()
    call_me_users = _get_users_list(call_me)

    text = (f'*Статистика по операторам за текущий месяц* \n'
            f'Принято заявок на подключение: {join_us_users} \n'
            f'_______________________________________________\n'
            f'Принято обратных звонков: {call_me_users} \n'
            )

    t_bot.send_message(message.chat.id, text, parse_mode='markdown')


@t_bot.callback_query_handler(func=lambda call: True)
def get_callback_user(call):
    if call:
        message = call.message
        user = call.from_user
        
        if user.username:
            user_data = f'@{user.username}'
        elif user.last_name and user.first_name:
            user_data = f'{user.last_name} {user.first_name}'
        elif user.last_name:
            user_data = user.last_name
        else:
            user_data = user.first_name

        data = call.data.split('.')
        if data[0] == 'join_us':
            join_us = JoinUs.objects.filter(pk=data[1]).last()
            if not join_us:
                t_bot.send_message(message.chat.id, 'Произошла какая-то ошибка. Не могу найти заявку :(')
                return

            if join_us.status == 'accepted':
                t_bot.send_message(message.chat.id, 'Заявка уже обработна другим оператором.')
                return

            join_us.status = 'accepted'
            join_us.user = user_data
            join_us.save()

            t_bot.edit_message_text(chat_id=message.chat.id, message_id=message.message_id,
                                text=f'{message.text}\nЗаявку принял(а) {user_data}',
                                reply_markup=None)

        elif data[0] == 'call_me':
            call_me = CallMe.objects.filter(pk=data[1]).last()
            if not call_me:
                t_bot.send_message(message.chat.id, 'Произошла какая-то ошибка. Не могу найти заявку :(')
                return

            if call_me.status == 'accepted':
                t_bot.send_message(message.chat.id, 'Заявка уже обработна другим оператором.')
                return

            call_me.status = 'accepted'
            call_me.user = user_data
            call_me.save()

            t_bot.edit_message_text(chat_id=message.chat.id, message_id=message.message_id,
                                text=f'{message.text}\nЗаявку принял(а) {user_data}',
                                reply_markup=None)

        elif data[0] == 'month':
            first_day = datetime.date.today().replace(day=1)
            current_time = datetime.datetime.now()

            join_us = JoinUs.objects.filter(status='accepted', created_at__gte=first_day, created_at__lte=current_time).all()
            join_us_users = _get_users_list(join_us)

            call_me = CallMe.objects.filter(status='accepted', created_at__gte=first_day, created_at__lte=current_time).all()
            call_me_users = _get_users_list(call_me)

            text = (f'*Статистика по операторам за текущий месяц* \n'
                    f'Принято заявок на подключение: {join_us_users} \n'
                    f'_______________________________________________\n'
                    f'Принято обратных звонков: {call_me_users} \n'
                    )

            t_bot.edit_message_text(chat_id=message.chat.id, message_id=message.message_id, text=f'error', parse_mode='markdown')

applications/core/models.py:

from ckeditor_uploader.fields import RichTextUploadingField
from django.db import models

STATUS_CHOICES = (
    ('new', 'Новая заявка'),
    ('accepted', 'Принятая заявка'),
)


class City(models.Model):
    title = models.CharField('Город', max_length=200)
    slug = models.SlugField('Слаг города', max_length=50, unique=True, db_index=True)
    is_active = models.BooleanField(default=True)

    class Meta:
        verbose_name = 'город'
        verbose_name_plural = 'города'

    def __str__(self):
        return self.title


class JoinUs(models.Model):
    OWNERSHIP_CHOICES = (
        ('fiz', 'Физическе лицо'),
        ('yur', 'Юридическое лицо'),
    )

    FORM_TYPE_CHOICES = (
        ('gpon', 'GPON'),
        ('4g', '4G'),
        ('smart', 'Smart TV'),
        ('neo', 'NEO TV'),
    )

    form_type = models.CharField('Тип заявки', max_length=50, choices=FORM_TYPE_CHOICES, default='')
    name = models.CharField('Имя', max_length=100)
    phone = models.CharField('Номер телефона', max_length=100)
    address = models.CharField('Адрес', max_length=150)
    ownership = models.CharField('Форма собственности', max_length=50, choices=OWNERSHIP_CHOICES, default='')

    user = models.CharField('Оператор принявший заявку', max_length=255, blank=True, default='')
    status = models.CharField('Статус заявки', max_length=50, choices=STATUS_CHOICES, default='new')

    created_at = models.DateTimeField('Дата поступления', auto_now_add=True)

    class Meta: 
        ordering = ['-created_at']
        verbose_name = 'заявка'
        verbose_name_plural = 'заявки'

    def __str__(self):
        return f'{self.name} - {self.phone}'


class CallMe(models.Model):
    name = models.CharField('Имя', max_length=100)
    phone = models.CharField('Номер телефона', max_length=100)

    user = models.CharField('Оператор принявший заявку', max_length=255, blank=True, default='')
    status = models.CharField('Статус звонка', max_length=50, choices=STATUS_CHOICES, default='new')

    created_at = models.DateTimeField('Дата поступления', auto_now_add=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = 'звонок'
        verbose_name_plural = 'звонки'

    def __str__(self):
        return f'{self.name} - {self.phone}'


class Vacancy(models.Model):
    title = models.CharField('Заголовок', max_length=100)
    short_description = models.CharField('Краткое описание', max_length=250,
                                         help_text='Краткий текст в списке вакансий для вовлечения соискателей.')
    description = RichTextUploadingField('Описание')

    created_at = models.DateField('Дата создания', auto_now_add=True)

    class Meta:
        ordering = ['-created_at']
        verbose_name = 'вакансия'
        verbose_name_plural = 'вакансии'

    def __str__(self):
        return self.title


class NeoTvFiles(models.Model):
    MOBILE_FILE_TYPE_CHOICES = (
        ('win', 'Windows'),
        ('macos', 'Mac OS'),
        ('armv7', 'Android arm v7'),
        ('armx64', 'Android arm x64'),
        ('armx86', 'Android arm x86'),
        ('youtube', 'YouTube плеер'),
    )
    type = models.CharField('Тип файла', max_length=50, unique=True, choices=MOBILE_FILE_TYPE_CHOICES)
    url = models.FileField('Файл для загрузки', upload_to='neo_tv_files/')

    class Meta:
        verbose_name = 'приложение NEO TV'
        verbose_name_plural = 'приложения NEO TV'

    def __str__(self):
        return self.get_type_display()

Бот запускается через management/commands командой python manage.py start_bot
django версии 2.2


Ответы (1 шт):

Автор решения: Dmitri Galkin

Ошибка в этой строке

t_bot.send_message(message.chat.id, text, parse_mode='markdown')
Bad Request: can\'t parse entities: Can\'t find end of the entity starting at byte offset 186"}

Во-первых используйте MarkdownV2, так как Markdown устарел.

Если поменять на V2 то ошибка немного изменится

Can't find end of Italic entity at byte offset 186

Вы используете строку ________________________ как разделитель, но markdown думает что вы хотите форматировать текст в курсив, но не видит конца.

_Italic example 2_

Поэтому если убрать строку _______________, то все заработает.

Исправленный вариант c переносом строки

text = (
    f'*Статистика по операторам за текущий месяц* \n'
    f'Принято заявок на подключение: \n'
    f'\n\n\n'
    f'Принято обратных звонков:  \n'
)
bot.send_message(message.chat.id, text, parse_mode="MarkdownV2")
→ Ссылка