@vikholodov

Как получить поле объектов из inlines Django?

При смене статуса отправляем пользователю email с объектами Order, при изменении в админке поля total в модели OrderItem (OrderItemInline(admin.StackedInline) отправляется старое значение из бд, не пойму как отловить изменения в OrderItemInline и записать их в бд перед отправкой юзеру =/
class OrderItemInline(admin.StackedInline):
    model = OrderItem
    fields = ['total', 'product', 'quantity']
    readonly_fields = ('product',)
    extra = 0
    can_delete = True


class OrderAdmin(admin.ModelAdmin):
    list_display = ['id', 'status', 'created']
    fields = ['status', 'order_message']
    list_filter = ['status', 'region', 'created', 'updated', ]
    empty_value_display = '-empty-'
    inlines = [OrderItemInline]
    readonly_fields = ('region', 'address', 'email', 'phone', 'total_price', 'order_message')

    def save_model(self, request, obj, form, change):
        test = OrderItem.objects.filter(order__id=int(obj.id))
        for i in test:
            print(i.total)

        super(OrderAdmin, self).save_model(request, obj, form, change)
        if "status" in form.changed_data:
            if obj.status == 'Ожидает оплаты':
#передаю obj в контекст и отправляю html письмо
  • Вопрос задан
  • 225 просмотров
Решения вопроса 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Django
Седой и строгий
Вместо метода save_model придётся использовать save_formset.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Sovetnikov
технический директор pulsprodaj.ru
Если при изменении статуса заказа надо отправить оповещение пользователям, то save_model в ModelAdmin это не самое лучше место, вернее даже худшее из приходяших на ум.
Статус заказа может быть изменен и в других местах ... (до уровня тригеров в БД опускаться не будем).

Используйте post_save сигнал. Только неудобство, что надо будет вручную определять изменился ли статус, на тостере было про это.

Если уж хотите в save_model, то учитывайте что Order изменится в БД только когда транзакция закомитится (а вы уверены что у вас транзакции нет?) Соответственно:
from django.db import connection
connection.on_commit(lambda: send_order_email(obj.pk))

И в send_order_email зачитывайте заказ и БД ...
Если хотите ускорить работу send_order_email в некоторых случаях и иметь возможность передать ему уже загруженный order с prefetch_related например, то сделайте просто:
def send_order_email(order):
   if not isinstance(order, Order):
        order = Order.objects.get(pk=order)
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы