As far as I can tell, running a script from python manage.py shell
like python manage.py shell < import.py
is done synchronously:
# models.py
class PersonManager(models.Manager):
def generate_num_children(self, persons):
for person in persons:
person.generate_num_children()
class ParentManager(models.Manager):
def generate_num_grandchildren(self, parents):
for parent in parents:
parent.generate_num_grandchildren()
class Person(models.Model):
objects = PersonManager()
num_children = models.IntegerField(default=0)
parent = models.ForeignKey(related_name="children")
def generate_num_children(self):
self.num_children = 1
self.save()
class Parent(models.Model):
objects = ParentManager()
num_grandchildren = models.IntegerField()
def generate_num_grandchildren(self):
num = 0
for child in self.children.all():
num = child.num_children
self.num_grandchildren = num
self.save()
# import.py
parent = Parent.objects.create(id=1)
person1 = Person.objects.create(id=2, parent=parent)
person2 = Person.objects.create(id=3, parent=parent)
person3 = Person.objects.create(id=4, parent=parent)
persons = Person.objects.all()
Person.objects.generate_num_children(persons)
parent.generate_num_grandchildren()
# python manage.py shell
Parent.objects.get(id=1).num_grandchildren # Returns 0
When I enter each line individually in python manage.py shell
or in a test
file however, the code runs asynchronously and gives me the correct result:
parent = Parent.objects.create(id=1)
person1 = Person.objects.create(id=2, parent=parent)
person2 = Person.objects.create(id=3, parent=parent)
person3 = Person.objects.create(id=4, parent=parent)
persons = Person.objects.all()
Person.objects.generate_num_children(persons)
parent.generate_num_grandchildren()
Parent.objects.get(id=1).num_grandchildren # Returns 3
So how can I make my import.py
file async?
# import.py
# Run first
parent = Parent.objects.create(id=1)
person1 = Person.objects.create(id=2, parent=parent)
person2 = Person.objects.create(id=3, parent=parent)
person3 = Person.objects.create(id=4, parent=parent)
persons = Person.objects.all()
Person.objects.generate_num_children(persons)
# Run only when previous section is complete
parent.generate_num_grandchildren()
CodePudding user response:
A Django shell script is normal Python, so you can use any of the build-in features for running asynchronous code in Python:
- Threads
- Processes
- Asyncio
Or you can use a task queue system like Celery for it.
If you are not already using something like Celery on your site, I would suggest looking into threads.