Асинхронный запуск сценария из "оболочки 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, я бы посоветовал обратить внимание на потоки.

Вернуться на верх