How to bulk update Django model values ?

Hi, so i know how to do single value update, and thats what i was trying in the below code

I want to update my links as they are messed up so this is what i did.

from testing.models import retailer

prods = retailer.objects.filter(shop = "Adidas", category = "Slippers")

links = []

serial = []

for all in prods:
  links.append(f'https://adidas.com{all.links.replace("https://adidas.com","")}')
  serial.append(all.id)


for serial,links in zip(serial,links):
  retialer.objects.filter(id=serial).update(links=links)

but i get an error in the end, int object is not iterable

Please Help, Thanks

Which line is throwing the error?

(Note: Thereā€™s an easier way to do this, but letā€™s handle this first.)

@ KenWhitesell
Iā€™d bet money on the id since it says int and the id is not only an int, but in the loop.

@ firaki12345
I know this doesnā€™t solve the issue youā€™re having with your current methodology, but Iā€™d just use SQL and do it on the DB end. Iā€™d just write some updates. But maybe you donā€™t have access to you DB backend?

But Iā€™d just do something like update prods set links = ā€˜blahblahā€™ where links = ā€˜blahblahā€™ if youā€™re trying to update everything that matches that where anyway.

Iā€™d cover that bet, with odds.

Iā€™ve got a suspicion I know what it likely is, but the complete traceback wasnā€™t provided and Iā€™ve got the feeling that this is a ā€œretypeā€ of the code used and not a copy/paste. (Notice the misspelling of ā€œretialerā€ on the last line.)

So rather than make guesses, Iā€™ll wait for the OP to post the traceback.

hi sorry for the confusion. i finally figured it out thanks to another thread.

for item in prods:
    link = f'https://...'
    item.links = link
    item.save()

hi sorry for the confusion. i finally figured it out thanks to another thread.

for item in prods:
    link = f'https://...'
    item.links = link
    item.save()

works very well

It works - but youā€™re executing separate queries for each item.

The update function on a queryset performs the updates on all members of the queryset, not just one at a time.

So, assuming that youā€™re trying to strip the first 18 characters from the links field of the retailer class, your entire block of code can be replaced by:

Retailer.objects.filter(
    shop='Adidas', 
    category='Slippers', 
    links__startswith='https://adidas.com'
).update(links=Substr(F('links'), 19))

It will be a benefit to you to start thinking of querysets as sets upon which operations can be performed - where those operations are performed on every member of the set without needing to explicitly iterate over those elements of that set.

Similarly, if for some reason you needed to iterate over those elements, itā€™s a lot better to do something like:

prods = retailer.objects.filter(shop = "Adidas", category = "Slippers")

for prod in prods:
    prod.links = 'new link'
    prod.save()

No need for you to manage indexes and explicit references.

(The first version above is still far superior to this, this would be useful if what you needed to do couldnā€™t be done in the context of an update function.)

Side note:

This is not correct in that youā€™re reassigning the values of serial and links to the elements of serial and links. You need to use different variables for the lists than for the elements youā€™re referring to in the list.

When you need to do something like this, the more appropriate pattern would be closer to:

links = []
serials = []

for serial, link in zip(serials, links):
    ...

(Note the change in variable names.)

1 Like