[Django]-Is there any way around saving models that reference each other twice?

4đź‘Ť

âś…

There is no way around it, you need to save one of the objects twice anyway.

This is because, at the database level, you need to save an object to get its ID. There is no way to tell a sql database “save those 2 objects and assign the ids to those fields on the other object”. So if you were to do it manually, you would INSERT the first object with NULL for the FK, get its ID back, INSERT the second object with the ID of the first one, get its ID back, then UPDATE the first object to set the FK.
You would encapsulate the whole thing in a transaction.

So what you’re doing with the ORM is the closest you can get. You may want to add the following on top of that:

1) Use a transaction for the changes, like this:

from django.db import transaction

with transaction.atomic():
    many, one = Many(), One()
    one.save()
    many.owner = one
    many.save()
    one.current = many
    one.save(update_fields=['current']) # slight optimization here

2) Now this is encapsulated in a transaction, you would want to remove the null=True. But you cannot, as those are, unfortunately, checked immediately.
[edit: it appears Oracle might support deferring the NOT NULL check, so if you’re using Oracle you can try dropping the null=True and it should work.]

You’ll probably want to check how your code reacts if at a later point, when reading the db, if for some reason (manual editing, bugged insert somewhere, …) one.current.owner != one.

👤spectras

Leave a comment