Question

I'm using django 1.6, and I have 2 models referencing each other like so:

class Person(models.Model):
   address = models.ForeignKey('Address', blank=False)

class Address(models.Model):
   person = models.ForeignKey(Person, blank=False)

The reason I have cyclic foreign key's is for data integrity. Because an address may be assigned to exactly one user, and a user must have at least one address. And yes, I know I can live without this, but I would rather not.

I'm using PostgreSQL with my foreign keys DEFERRABLE INITIALLY DEFERRED, and I want to use transactions to insert the data into those tables. However, when I try to use transaction.atomic():, it does not behave as expected within my view.

Here is what I am doing:

with transaction.atomic():
    addr = Address(street='125 fake street')
    addr.save()

    person = Person()
    person.address_id = addr.id

    addr.person_id = person.id

    addr.save()
    person.save()

However, I keep getting an IntegrityError the first time I call addr.save()

Any suggestions what I'm doing wrong? Is there a better way to to that?

Was it helpful?

Solution

The problem here is, because PostgreSQL does not wait untill the end of transaction to check for NOT NULL.

sql-set-constraints reference

"NOT NULL and CHECK constraints are always checked immediately when a row is inserted or modified (not at the end of the statement)."

And my columns were set to NOT NULL.

As a workaround, I'm doing this

with transaction.atomic():
    addr = Address()
    addr.person_id = 0    # setting this temporarily to Zero
    addr.save()

    person = Person()
    person.address_id = addr.id
    person.save()

    addr.person_id = person.id
    addr.save()

This allows me to insert into the database, and update the foreign keys later, and still fail with if no foreign key matches, because I will never have a value of Zero for id value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top