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
)
таким образом запрос в базу не происходит на каждой итерации