Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ORM - confusion about Router.allow_relation()

In the documentation of the new version of Django there is an ambiguity between what is said in the text and the code shown.

In the section that describes the multidatabase configuration it speaks about the router configuration, and there is a method:

allow_relation(obj1, obj2, **hints)

Return True if a relation between obj1 and obj2 should be allowed, False if the relation should be prevented, or None if the router has no opinion. This is purely a validation operation, used by foreign key and many to many operations to determine if a relation should be allowed between two objects.

At the end of the documentation there is this:

Django doesn’t currently provide any support for foreign key or many-to-many relationships spanning multiple databases. If you have used a router to partition models to different databases, any foreign key and many-to-many relationships defined by those models must be internal to a single database.

This is because of referential integrity. In order to maintain a relationship between two objects, Django needs to know that the primary key of the related object is valid. If the primary key is stored on a separate database, it’s not possible to easily evaluate the validity of a primary key.

But the router code given as an example is the following:

def allow_relation(self, obj1, obj2, **hints):
     """
     Relations between objects are allowed if both objects are
     in the primary/replica pool.
     """
     db_list = ('primary', 'replica1', 'replica2')
     if obj1._state.db in db_list and obj2._state.db in db_list:
         return True
     return None

So even if the objects are from different databases the relation is allowed by the software.

Does anyone know what it means?

Thanks.

like image 532
softwareplay Avatar asked Feb 15 '16 08:02

softwareplay


1 Answers

That's a good question, and I agree that the multiple-database docs are not as clear as they could be.

The thing to keep in mind is that there are basically two use cases for multi-DB: putting different data (models) on different databases; and setting up a primary / replica DB structure. These use cases are both represented in the primary example in the documentation.

In the different-data scenario, you definitely want allow_relation() to reject any relations between two different databases. But in the primary-replica scenario, you have the same data on all the databases, so it's OK to allow relations between any of them.

So if you get one model instance from replica1 and another from replica2 (due to the random choice of database for reads), it would be OK to allow a relation between them since the same data exists on primary, and that's where the new model data will be written.

like image 123
Kevin Christopher Henry Avatar answered Oct 21 '22 06:10

Kevin Christopher Henry