Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: "Soft" ForeignField without database integrity checks

I have a Django project that has multiple django "apps". One of them has models to represent data coming from an external source (I do not control this data).

I want my other apps to be able to have references to this "external app" but I want to avoid all the fuzz of the database integrity checks. I don't want the db to have any constraints on these "soft foreign keys".

Do you know how I can code a custom field that will emulate a real Django ForeignKey without creating a hard constraint on the database?

Maybe this already exists, but I didn't have any luck on Google.

Thanks in advance for the help :-)

NB: I'm aware of the generic relations system with the content_types. But I don't want generic relations. I want specific relations to identified models only without hard integrity constraints.

EDIT:

I found related links:

  • Django ForeignKey which does not require referential integrity?
  • Understanding / mySQL aka tricking ForeignKey relationships in Django

But I didn't find a proper answer to my question. :(

EDIT 2012, june 4:

I've looked deep into django's code to find what needs to be done, but I think that simply subclassing ForeignKey will not be enough. Could you give me some directions on how to do this?

NB: I use South for managing my database schema, so I figure I'll need to do something about that too. But it may be out of the subject here :)

like image 459
Robin Avatar asked May 16 '12 17:05

Robin


2 Answers

If you just want to disable the ForeignKey constraint check on a field, then just add db_constraint=False to that field.

user = models.ForeignKey('User', db_constraint=False)

See also: Django - How to prevent database foreign key constraint creation

like image 138
Joris Avatar answered Oct 05 '22 23:10

Joris


Piggybacking off of marianobianchi's comment, one of the options for ForeignKey.on_delete is

DO_NOTHING: Take no action. If your database backend enforces referential integrity, this will cause an IntegrityError unless you manually add a SQL ON DELETE constraint to the database field (perhaps using initial sql).

This combined with disabling foreign key constraints at the db level should do the trick. From what I can tell, there are two ways of doing this. You could disable fk constraints entirely like this:

from django.db.backend.signals import connection_created
from django.dispatch import receiver

@receiver(connection_created)
def disable_constraints(sender, connection):
    connection.disable_constraint_checking()

It looks like the django db backends offer a constraint_checks_disabled context manager, too, so you could wrap the relevant db accesses in code like this to avoid disabling the checks throughout:

from django.db import connection
with connection.constraint_checks_disabled():
    do_stuff()
like image 27
dokkaebi Avatar answered Oct 05 '22 22:10

dokkaebi