views:

220

answers:

1

The geonames database has two models that refer to each other. In a postgres database, reference is provided by foreign key relationships. The problem is writing data to the database - writing to one table without having the referenced id in the other table violates a foreign key contraint.

Class Geoname
    id = IntegerField(primary_key=True)
    admin_1 = foreignkey('Admin1', null=True, db_index=True)

Class Admin1
    country = models.ForeignKey(Country, db_index=True)
    geoname = models.ForeignKey(Geoname, related_name="admin1_set", db_index=True)

Is there a way to write to a postgres database with this schema, avoiding violating foreign key contraints?

If not, I think a possible solution might be to drop admin_1 from geoname class, but would django still pick up on geoname.admin1_set? Remember, the data is being written directly to the database without the ORM - i think backwards relations are something that is created by the django ORM - I don't know how they are represented at the database level).

A: 

First: Having a cyclic relationship in your database schema means a bad design of your schema.

Backwards reference is indeed created by the ORM, but it is created on the fly (on reading) not on writing.
Otherwise it would not be possible to load fixtures for automated tests...

Is it a one-to-one relation? If so, you can use the OneToOneField:

Class Geoname
    id = IntegerField(primary_key=True)
    admin_1 = OneToOneField('Admin1')

Class Admin1
    country = models.ForeignKey(Country, db_index=True)

I hope these classes inherit from django.db.models.Model in your real code!

If it is not a one-to-one relation you can do this:

Class Geoname
    id = IntegerField(primary_key=True)

Class Admin1
    country = models.ForeignKey(Country, db_index=True)
    geoname = models.ForeignKey(Geoname, db_index=True)

and you have access to all Admin1 objects that refer to a certain Geoname by

g = Geoname.objects.get(id=1)
g.admin1_set.all() # Returns all Admin1 objects related to Geoname

You can read about such queries in the documenation.

Felix Kling
Thanks for the advice! It's someone else's code that I'm trying to figure out - I wasn't sure if cyclic relationships were okay, or even possible!
Cody