2

How do I create a copy of a Django model instance along with a related One-to-One field?

Copying the model instance works fine, but when I try to create a copy of the one-to-one model, all the fields of that model become blank. Here's what I did:

            new_address = self.object.designer.address # type Address
            new_address.pk = None
            new_address.save()

            new_contact = self.object.designer # type Contact
            new_contact.pk = None
            new_contact.address = new_address

            new_contact.save()

            self.object.shippinginfo.contact = new_contact
            self.object.shippinginfo.save()

The Contact model has a one-to-one relationship with the Address model. I tried printing out the values, after creating the new address, the values were correct when I printed them out, but then when I save the address to the address field of the new contact, all of the fields of the address are blank except the pk...

2 Answers 2

1

To answer your direct question, you may want to use the save(force_insert=True) function and see if that fixes it. I would also check what you get if you call Contact.objects.all().count() and the same for Address, so you can ensure you are adding new records.

That said, I personally will recommend against what you are trying to do, which in my book, is a hack. Instead, just write the few extra lines of code and properly call the Adress.objects.create() and Contact.objects.create with the fields set from the other records. e.g.

old_address = self.object.designer.address
new_address = Address.objects.create(line1=old_adress.line1, line2=old_address.line2, etc)

Or even better, use an AddressManager:

class AddressManager(models.Manager):
    def create_copy(self, obj):
        address = self.create(line1=obj.line1, etc.)
        return address

class ContactManager(models.Manager):
    def create_copy(self, obj):
        new_address = Address.objects.create_copy(obj.address)
        contact = self.create(name=obj.name, address=new_address, etc.)
        return contact

new_contact = Contact.objects.create_copy(old_contact)

Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

I tried creating a copy by specifying all of the fields, but it still doesn't work. The problem seems to be that instead of setting new_contact.address to new_address, what happens is that it creates a new instance of Address with blank fields...
If you haven't solve it, can you show us how you are declaring the onetoone on your Models?
0

I think you're not clear about how to define relationship. If Contact model has one to one relationship with Address model, then one object of Contact class can be related to one object of Address model. It'll be defined as:

class Contact(models.Model):
    # field_one = ...
    # field_two = ...
    # and so on...

class Address(models.Model):
    contact = OneToOneField(Contact)
    # and more model fields...

This way you can associate one Contact object to one Address object. If you want to have more than one address for one contact then you should use ForeignKey.

For one Contact object having related to many Address instances, you can define relationship as:

class Contact(models.Model):
   # field_one = ...
   # field_two = ...
   # and so on...

class Address(models.Model):
    contact = ForeignKey(Contact)
    # and more fields...

But here an Address object can be associated to a particular Contact object only.

You can read about Many To Many realtionship here.

And you don't have to initialize pk field as it is automatically updated/added.

2 Comments

Currently address is a field of the contact model with a one-to-one relationship: class Contact(models.Model): address = OneToOneField(Address) In this case, I don't want a foreign key to address.... I want to copy an instance of address and set that to the copy of contact that I created. This is because when a certain action is done, I don't want to edit the existing contact.address object but rather make a copy of this and save it elsewhere...
You can get contact object to be copied using old_contact = Contact.objects.get(id = <someid>). Then use new_contact = Contact( ) to create a new object. And update address field of new_contact using new_contact.address = old_contact.address. Then new_contact.save(). Using ForeignKey will make this very easy. You won't have to create a new object of Contact in that case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.