0

I have a model:

class MyModel(models.Model):
    fieldA = models.IntegerField()
    fieldB = models.IntegerField()
    fieldC = models.IntegerField()

Now, let's get a QuerySet, e.g.

qs = MyModel.objects.all()

I'd like to be able to change fieldB and fieldC of all instances in qs with the same value and save them as NEW records in my database. I need something similar to qs.update(fieldB=2, fieldC=3) but I don't want to override the original records in qs. Is there a Django-way to do so (i.e., something not involving a manually coded for loop)?

Sirion
  • 804
  • 1
  • 11
  • 33
  • Not sure how I mark duplicate (new to this site), but your answer is here: http://stackoverflow.com/questions/4733609/how-do-i-clone-a-django-model-instance-object-and-save-it-to-the-database – michaelb Oct 01 '14 at 14:55
  • Thanks, but that applies to a single instance, is there a way to do it for all instances? (again, something other than the usual `for` loop, possibly something that insert all records with a single query). – Sirion Oct 01 '14 at 15:03

1 Answers1

0

I'm not aware of a Django call that will do what you want in a single call, like update does.

This is the closest I've been able to come to. Assuming that the objects you wanted to operate on are in qs then:

MyModel.objects.bulk_create(
    MyModel(**{pair[0]: pair[1] for pair in x.iteritems() 
                if pair[0] != MyModel._meta.pk.name}) 
     for x in qs.values())

Notes:

  1. qs.values() returns one dictionary per object in qs.

  2. The {pair[0]...} expression is a dictionary comprehension that creates a new dictionary minus primary field defined on MyModel.

  3. MyModel(**...) creates a new MyModel object with its primary key set to None. It effectively creates a copy.

  4. bulk_create creates all the objects in one query. It has caveats that one should be aware of.

If it needs be mentioned, what you have here are dict and list comprehensions, not for loops.

Louis
  • 146,715
  • 28
  • 274
  • 320