4

I have an Order (1) and OrderLine (n) model, here order can have multiple order-lines. This is all run from inside the Django-admin, where the OrderLine is setup as part of the inlines on OrderAdmin(admin.ModelAdmin).

Simplified like this:

   class OrderLine(admin.StackedInline):
     pass

   @admin.register(Order)
   class OrderAdmin(admin.ModelAdmin):
     inlines = [OrderLine]

I registered for the pre_save and post_save on on both models. Django calls these signals in the following order:

  1. Order | pre_save
  2. Order | post_save
  3. OrderLine 1 | pre_save
  4. OrderLine 1 | post_save
  5. OrderLine 2 | pre_save
  6. OrderLine 2 | post_save
  7. OrderLine n | pre_save
  8. OrderLine n | post_save

The issue I'm having is that I would like to change the order of the signals called, as follows:

  1. Order | pre_save
  2. OrderLine 1 | pre_save
  3. OrderLine 1 | post_save
  4. OrderLine 2 | pre_save
  5. OrderLine 2 | post_save
  6. OrderLine n | pre_save
  7. OrderLine n | post_save
  8. Order | post_save

Since I need to do a few calculations in each OrderLine, and those results needs to be used in the Order post. But the post signal is already been called.

The only solution I see is to call my code on each OrderLine post signal, which is a bit redundant, especially when you have many order-lines.

What would be the best / better way to tackle this?

Roger
  • 7,535
  • 5
  • 41
  • 63
  • You can call saving `OrderLine1,2,N` inside `pre_save` signal of `Order`. – Sergey Pugach Dec 16 '19 at 12:41
  • @SergeyPugach not sure what you mean, how you save the order-lines in the `pre_save`? When I use `post_save` inside the `Order`, I still see the old data of each `OrderLine`. So that doesn't work, which makes sense since I can see the order-lines are updated after the `Order` has been saved. – Roger Dec 16 '19 at 12:53
  • Could you add code with your models and that part of code where Order and OrderLine is saved now& – Sergey Pugach Dec 16 '19 at 13:02
  • @SergeyPugach well it's not much use I think. This is al run from within `admin.ModelAdmin`, so not much of code. Other than the 2 functions for `pre_save` and `post_save`. I will updated my question, since this is relevant. – Roger Dec 16 '19 at 13:32
  • You have shared content from `admin.py`, but I asked your models from `models.py`. – Sergey Pugach Dec 16 '19 at 13:39
  • @SergeyPugach nothing there just a bunch of fields that are common in a Order/Orderline construction (name, address, order_total, etc..) and on the OrderLine: product_name, quantity, price, vat, total. My problem is in the order which DjangoAdmin fires the signals. And that the master is called pre *and* post, before the detail rows are updated. Which strikes me as odd. – Roger Dec 16 '19 at 13:40

1 Answers1

1

I have been side-tracked, thinking you should solve this via signals.

Apparently you can (and should) implement in your admin class (admin.ModelAdmin) the following method:

 # example
 def save_related(self, request, form, formsets, change):
    super(OrderAdmin, self).save_related(request, form, formsets, change)
    # get the master obj
    order = form.instance
    order.total = Decimal.from_float(0.0)
    for ol in order.order_lines.all():
        order.total += ol.total order.total

This is called after all related objects are updated.

Roger
  • 7,535
  • 5
  • 41
  • 63