I have a simple class that includes a GenericRelation
class Item(models.Model):
name = models.CharField ( max_length=50, null=True, blank=True )
image = generic.GenericRelation开发者_JS百科(Image)
class Image(models.Model):
file = models.FileField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
To make a copy of an Item I can set Item.id = None and save:
item = Item.objects.get(id=3)
item.id = None
item.save()
# item is now a copy of the original item
Unfortunately this doesn't copy the image field to the new instance.
I tried manually copying it over:
item = Item.objects.get(id=3)
images = item.image.all()
item.id = None
item.save()
item.image = images
However this removes the images from the original instance, effectively moving them to the second instance instead of copying.
What's a good way to copy the images over to the new instance?
Your problem is that with the way you currently have your models defined each Image is only capable of referencing one 'Item' (or any other model).
Would this accomplish what you need?:
class Image(models.Model):
file = models.FileField()
class Item(models.Model):
name = models.CharField ( max_length=50, null=True, blank=True )
images = models.ManyToManyField(Image, related_name="images_set")
where before to access an item's image you might have code similar to:
images_of_item = my_item.image.all()
you would now have something similar to:
images_of_item = my_item.images_set.all()
or if before you were using Generic Relations because you needed to keep track of an 'Image' for different objects of different models, but you don't need to have multiple images per Item, this may work better:
class Image(models.Model):
file = models.FileField()
class Item(models.Model):
name = models.CharField ( max_length=50, null=True, blank=True )
image = models.ForeignKey(Image)
where as before instead of code similar to:
image_of_item = my_item.image.all()
you would have code similar to... well:
the_items.image = my_item.images.all()
If you look at the table structure that django generates for the models you included in your question, its likely that you have a table called, appname_Image, which has a FK column that connects an Image with an instance of a model based on two fields, content_type_id
and object_id
, knowing that each Image is represented by a single row, you can see that each 'Image' will only be able to be connected to a single 'Item' (or any other model).
If you were to use my first suggestion, Django would generate a joiner-table which would allow you to associate many Images each with many Items. -- If what you were trying to accomplish with generic foreign keys was to enable multiple types of models to be associated with Images, and you want multiple images per model, this is the way to go, add a ManyToMany field to each model that needs to be associated with multiple Images
If you were to use my second example, Django would put the responsibility of maintaining the Item-Image relationship on the Item (and other Models if you add a similar ForeignKey) and its table. Your appname_Item table would likely have a FK column named image_id. -- If what you were trying to accomplish with generic foreign keys was to enable multiple types of models to be associated with Images, but you don't need multiple images per model, this is the way to go, add a ForeignKey field to each model that needs to be associated with a single image
To answer my own question: I ended up manually making a copy of the image and setting its object_id:
item = Item.objects.get(id=3)
image = item.image.all()[0]
image.id = None
image.object_id = new_item.id
image.save()
精彩评论