Асинхронный запуск сценария из "оболочки python manage.py"?
Насколько я могу судить, запуск скрипта из python manage.py shell
как python manage.py shell < import.py
выполняется синхронно:
# 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
Когда я ввожу каждую строку по отдельности в python manage.py shell
или в файл test
, однако, код выполняется асинхронно и дает правильный результат:
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
Итак, как я могу сделать мой import.py
файл асинхронным?
# 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()
Сценарий оболочки Django - это обычный Python, поэтому вы можете использовать любую из встроенных функций для запуска асинхронного кода на Python:
- Потоки
- Процессы
- Asyncio
Или вы можете использовать для этого систему очередей задач, например Celery.
Если вы еще не используете на своем сайте что-то вроде Celery, я бы посоветовал обратить внимание на потоки.