@robocop45
Only python

Как отправлять всю информацию о заказе в одном сообщении в тг группу?

Задача: пользователь делает заказ и все данные о заказе присылаются админу в тг группу.
Работает все ок, но если к примеру в корзине 2 товара, то и сообщения 2, а такого быть не должно.

т.е нужно чтобы в одном сообщении были детали заказа(модель Order) и ВСЕ товары к данному заказу (модель OrderItem)

models

class Order(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='orders', on_delete=models.CASCADE)
    first_name = models.CharField('Имя', max_length=50)
    last_name = models.CharField('Фамилия', max_length=50)
    email = models.EmailField(verbose_name='Почта')
    address = models.CharField(max_length=250, null=True, blank=True, verbose_name='Точный адрес')
    city = models.CharField(max_length=100, null=True, blank=True, verbose_name='Город')
    created = models.DateTimeField(auto_now_add=True, verbose_name='Время создания')
    plants = models.ManyToManyField(Plant, through='OrderItem')
    telegram_name = models.CharField(max_length=50, verbose_name="Имя телеграм")
    phone_number = PhoneNumberField(blank=True, verbose_name='Номер телефона')

    def formatted_created(self):
        return self.created.strftime('%Y-%m-%d %H:%M')

    def get_total_cost(self):
        return sum(item.get_cost() for item in self.items.all())

    def __str__(self):
        return f'Заказал(-а) - {self.first_name}  {self.last_name}'
class OrderItem(models.Model):
    order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE)
    plant = models.ForeignKey(Plant, related_name='order_items', on_delete=models.CASCADE)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.PositiveIntegerField(default=1)
    time_created = models.DateTimeField(auto_now_add=True, verbose_name='Время создания')

    def get_cost(self):
        return self.price * self.quantity

    def __str__(self):
        return f'Заказ - {self.order}'


views
@login_required
@login_required
def create_order(request):
    cart = Cart(request)
    user = request.user

    if request.method == 'POST':
        form = OrderForm(request.POST)
        if form.is_valid():
            order = form.save(commit=False)
            order.user = user  # Установка текущего пользователя как создателя заказа
            order.save()
            order_id = None
            for item in cart:
                plant = item['product']
                quantity = item['quantity']
                price = item['price']
                order_item = OrderItem.objects.create(order=order, plant=plant, price=price, quantity=quantity) # get order using foreignkey
                order_id = order_item.order.id
                sendMessageTg(order_item)
            cart.clear()  # Очистка корзины

            return render(request, 'main/order_successful_created.html', {'order_id': order_id})  # Перенаправление на страницу подтверждения заказа
    else:
        initial_data = {'first_name': user.first_name, 'last_name': user.last_name, 'email': user.email}
        form = OrderForm(initial=initial_data, instance=Order(user=user))  # Передача начальных данных и экземпляра модели Order в форму

    return render(request, 'main/create_order.html', {'form': form, 'cart': cart})


bot.py

import requests
from .models import *


from datetime import datetime

from datetime import datetime

def sendMessageTg(order_item):
    if TelegramOrderMessage.objects.get(pk=1):
        tg_data = TelegramOrderMessage.objects.get(pk=1)
        token = str(tg_data.bot_token)
        chat_id = str(tg_data.chat_id)
        text = str(tg_data.message)

        order = order_item.order  # Получение объекта заказа
        order_item_data = {
            'plant': order_item.plant.plant_name,
            'price': order_item.price,
            'quantity': order_item.quantity,
            'time_created': order_item.time_created.strftime('%Y-%m-%d %H:%M')  # Форматирование времени создания
        }


        for field_name, field_value in order_item_data.items():
            text = text.replace(f'{{{{ {field_name} }}}}', str(field_value))

        # Формирование сообщения с использованием всех полей модели Order
        for field in order._meta.fields:
            field_name = field.name
            field_value = getattr(order, field_name)

            if field_value:
                if isinstance(field_value, datetime):
                    field_value = field_value.strftime('%Y-%m-%d %H:%M')  # Форматирование времени

                text = text.replace(f'{{{{ {field_name} }}}}', str(field_value))

        # Формирование сообщения с использованием полей модели OrderItem
        url_req = f"https://api.telegram.org/{token}/sendMessage?chat_id={chat_id}&text={text}"
        results = requests.get(url_req)


models(для бота)
class TelegramOrderMessage(models.Model):
    bot_token = models.CharField('Токен бота', max_length=100)
    chat_id = models.CharField('Id группы', max_length=100)
    message = models.TextField('Сообщение')

    def __str__(self):
        return self.bot_token


message в админке

Тестовое сообщение.
Имя: {{ first_name }}
Фамилия: {{ last_name }}
Почта: {{ email }}
Город: {{ city }}
Адрес: {{ address }}
Номер телефона: {{ phone_number }}
Telegram: {{ telegram_name }}
Время создания: {{ created }}
---------------------------
{{ plant }} 
{{ price }}
{{ quantity }}
{{ time_created }}
  • Вопрос задан
  • 65 просмотров
Решения вопроса 3
AlexNest
@AlexNest
Работаю с Python/Django
если к примеру в корзине 2 товара, то и сообщения 2, а такого быть не должно.

Почему, собственно, не должно? Вы сами проходитесь по объекту корзины и при каждой итерации вызываете sendMessageTg
for item in cart:
                ...
                sendMessageTg(order_item)

Хотите, чтобы было одно сообщение - вызывайте один раз, передавая, например, всю корзину. Ну и измените код функции так, чтобы она работала не с отдельным заказом, а со всеми в корзине.
Ответ написан
Комментировать
@maksam07
sendMessageTg(order_item).
Вам нужно работать не с каждой позицией, а с деталями заказа, как бы очевидно это не выглядело. Если вьюху полностью покажете, то может быть станет понятнее, куда переместить код

И тег телеграм тут лишний. У вас нет проблем с телеграмом, а только с формированием сообщения
Ответ написан
@robocop45 Автор вопроса
Only python
Ура! решение нашел.

views.py
@login_required
def create_order(request):
    cart = Cart(request)
    user = request.user

    if request.method == 'POST':
        form = OrderForm(request.POST)
        if form.is_valid():
            order = form.save(commit=False)
            order.user = user  # Установка текущего пользователя как создателя заказа
            order.save()
            order_id = None
            for item in cart:
                plant = item['product']
                quantity = item['quantity']
                price = item['price']
                order_item = OrderItem.objects.create(order=order, plant=plant, price=price, quantity=quantity) # get order using foreignkey
                order_id = order_item.order.id

            sendMessageTg(order)  # Отправить сообщение после создания всех товаров в заказе

            cart.clear()  # Очистка корзины

            return render(request, 'main/order_successful_created.html', {'order_id': order_id})  # Перенаправление на страницу подтверждения заказа
    else:
        initial_data = {'first_name': user.first_name, 'last_name': user.last_name, 'email': user.email}
        form = OrderForm(initial=initial_data, instance=Order(user=user))  # Передача начальных данных и экземпляра модели Order в форму

    return render(request, 'main/create_order.html', {'form': form, 'cart': cart})


bot.py

import requests

from main.models import OrderItem
from .models import *


from datetime import datetime


from datetime import datetime

def sendMessageTg(order_item):

    if TelegramOrderMessage.objects.get(pk=1):
        tg_data = TelegramOrderMessage.objects.get(pk=1)
        token = str(tg_data.bot_token)
        chat_id = str(tg_data.chat_id)
        text = str(tg_data.message)

        order = order_item  # Получение объекта заказа

        order_items = OrderItem.objects.filter(order=order)  # Получение всех OrderItem для текущего заказа

        order_items_text = ""  # Переменная для хранения текста всех OrderItem

        # Формирование текста для каждого OrderItem
        for item in order_items:
            item_data = {
                'plant': item.plant.plant_name,
                'price': item.price,
                'quantity': item.quantity,
                'time_created': item.time_created.strftime('%Y-%m-%d %H:%M')  # Форматирование времени создания
            }

            item_text = ""  # Переменная для хранения текста одного OrderItem

            # Формирование текста одного OrderItem
            for field_name, field_value in item_data.items():
                item_text += f"{field_name}: {field_value}\n"

            order_items_text += item_text + "\n"  # Добавление текста одного OrderItem к общему тексту всех OrderItem

        # Формирование сообщения с использованием всех полей модели Order
        for field in order._meta.fields:
            field_name = field.name
            field_value = getattr(order, field_name)

            if field_value:
                if isinstance(field_value, datetime):
                    field_value = field_value.strftime('%Y-%m-%d %H:%M')  # Форматирование времени

                text = text.replace(f'{{{{ {field_name} }}}}', str(field_value))

        # Добавление текста всех OrderItem к сообщению
        text = text.replace("{{ order_items }}", order_items_text)

        url_req = f"https://api.telegram.org/{token}/sendMessage?chat_id={chat_id}&text={text}"
        results = requests.get(url_req)
        print(results.json())


в админке

{{ order_items }}

т.е вынес функцию sendMessageTg и в bot,py обратился к элементам таким способом
order = order_item # Получение объекта заказа
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы