Saving models with NOT NULL ForeignKeys referencing each other

66 views
Skip to first unread message

antialiasis

unread,
Jan 21, 2014, 5:54:10 AM1/21/14
to django...@googlegroups.com
Hi,

I just bumped into this issue. Say I have the following models:


class Foo(models.Model):
    bar = models.ForeignKey('Bar', related_name='foos')

class Bar(models.Model):
    default_foo = models.ForeignKey(Foo, related_name='+')


Basically, the idea is that each bar has many foos, but one of them is the bar's default foo. Every foo must have an associated bar, and each bar must have a default foo, so both of the ForeignKey fields are NOT NULL.

This was working great until I realized that now I can't actually create any Foo or Bar objects, because I can't save a Foo object without setting its bar_id, and I can't save a Bar object without setting its foo_id.

Does Django have any kind of way around this, or is the solution just to allow null for one of them (dangerous for data integrity)? Or should I perhaps just not use this kind of circular reference altogether and instead go with something like an is_default field on the Foo model?

Russell Keith-Magee

unread,
Jan 21, 2014, 7:43:28 AM1/21/14
to Django Users
This is what database transactions are for. A transaction is a way to make a series of individual changes as a single atomic change in the database. 

In Django 1.6, the main way to implement transactional behaviour is to use the atomic decorator:


The only place this doesn't work is with MySQL, because it has a broken implementation of referential integrity. If you're using PostgreSQL (which implements referential integrity at the transaction boundary) or SQLite (which doesn't have referential integrity), a transaction will do the job.

If you have to use MySQL (and personally, I'd really recommend you don't), the approach you've described of making one of the fields nullable is what you have to do.

Yours,
Russ Magee %-)


antialiasis

unread,
Jan 22, 2014, 6:07:10 AM1/22/14
to django...@googlegroups.com
It didn't occur to me that this could be done with transactions, but in retrospect it seems obvious. Thanks for the quick response.
Reply all
Reply to author
Forward
0 new messages