Issue
I have an Animal
model and a Herd
model that looks like this:
from django_lifecycle.hooks import AFTER_CREATE
class Animal(models.Model):
parent = OneToOneField("self", related_name="child")
age = IntegerField()
class Herd(models.Model):
animal = OneToOneField(Animal)
total_age = IntegerField()
@hook(AFTER_CREATE)
def create_animal_child(self):
if self.animal.child.exists():
Herd.objects.create(parent=self, animal=self.animal.child)
def save_total_age(self):
total_age = self.animal.age
position = self.animal
while position.child.exists():
total_age += position.child.age
position = position.child
The idea being that you create your Animal
s. Then you create your Herd
for the topmost animal you want. The Herd's AFTER_CREATE
will then create a "chain" of all the Herd
objects for the Animal
's children, the children's children, and so on.
E.g.
a1 = Animal.objects.create(age=10)
a2 = Animal.objects.create(parent=a1, age=7)
a3 = Animal.objects.create(parent=a2, age=3)
h1 = Herd.objects.create(animal=a1)
# Two Herd objects with an "animal" field pointing to a2 and a3 respectively are automatically created
h1.save_total_age() # h1.total_age = 20 # 10 + 7 + 3
Which is all fine.
My problem is for my front-end, how can I tell when all the relevant Animal
AFTER_CREATE
hooks have finished running so I know to call my calculate_total_age
method?
So say I have the following REST API endpoints:
example.com/api/animals/<pk>
example.com/api/herds/<pk>
example.com/api/herds/<pk>/save_total_age
If I do a POST to example.com/api/herds/<pk>
to create a Herd
, I call save_total_age()
as soon as that "parent" Herd
is created - and not necessarily after all the "children" Herd
s have been created via the AFTER_CREATE
hook.
axios.post(
"example.com/api/herds/",
{animal_id: 1}
).then((response) => {
axios.post(
`example.com/api/herds/${response.data.pk}/save_total_age`,
{},
)
});
How can I set my backend signals and/or frontend async/await so that save_total_age()
only runs after my AFTER_CREATE
chain is complete?
Edit: My best solution right now is to add some condition to save_word_count()
that makes sure the Herd
chain has the same # of objects as the Animal
chain. If so, run the method. If not, return a bad request and retry the POST.
Solution
Signals (which are called by those hooks) run synchronously, not asynchronously. So when you call create()
for your first heard, it will always run the AFTER_CREATE
hook and create the 2nd Heard object, before it returns and let you run the save_total_age()
method.
In other words this should work just fine as it is.
Answered By - Erik Kalkoken
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.