Update связаных объектов одним запросом

Есть задача которая каждый день загружает посылки клиента (к примеру 3000 штук). Далее эти посылки создаются в базе. Нюанс в том что есть посылки в одинаковым package_number но с разным vas_code. Пример таких посылок:

Посылка 1 (основная посылка):

  • package_number = "370727320136718285"
  • vas_code = "0000"

Посылка 2 (дочерняя посылка):

  • package_number = "370727320136718285"
  • vas_code = "3234" (марка)

Посылка 3 (дочерняя посылка):

  • package_number = "370727320136718285"
  • vas_code = "5800" (коробка)

После создания всех посылок их нужно связать между собой - для дочерних посылок установить основную посылку как parent.

Пример модели

class Package(models.Model):
    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        null=True, blank=True
    )
    package_number = models.CharField(max_length=80, null=True, blank=True)
    vas_code = models.CharField(max_length=80, null=True, blank=True)

Сейчас это происходит приблизительно так:

packages = []
for item in response:
    package = Package.objects.create(**item)
    if package.vas_code == "0000":
        packages.append(package)

и затем кусок который я хотел бы заменить одним запросом (без использования for)

for package in packages:
    Package.objects.filter(~Q(vas_code='0000'), package_number=package.package_number).update(parent=package)

Спасибо @finally за то что натолкнул на мысль.

Решил задачу следующим путём

parent_packages = {}
child_packages = []
for item in response:
    package = Package.objects.create(**item)
    if package.vas_code == "0000":
        parent_packages[package.package_number] = package
    else:
        child_packages.append(package)

затем в функции которая должна связать посылки делаю

for child_package in child_packages:
    child_package.parent = parent_packages.get(
        child_package.package_number
    )

Package.objects.bulk_update(
    objs=child_packages,
    fields=['parent'],
    batch_size=1000
)

таким образом запрос в базу не происходит на каждой итерации

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