Marc
Marc

Reputation: 3596

django with multiple databases and foreignkeys for User

Suppose I have a django app on my server, but I wish to do authentication using django.contrib.auth.models where the User and Group models/data are on another server in another database. In Django, my DATABASES setting would be something like this:

DATABASES = {
    'default': {},
    'auth_db': {
        'NAME'      : 'my_auth_db',
        'ENGINE'    : 'django.db.backends.mysql',
        'USER'      : 'someuser',
        'PASSWORD'  : 'somepassword',
        'HOST'      : 'some.host.com',
        'PORT'      : '3306',
    },
    'myapp': {
        'NAME': 'myapp_db',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'localuser',
        'PASSWORD': 'localpass',
    }
}

DATABASE_ROUTERS = ['pathto.dbrouters.AuthRouter', 'pathto.dbrouters.MyAppRouter']

First question: will this work, ie will it allow me to login to my Django app using users that are stored in the remote DB 'my_auth_db'?

Assuming the answer to the above is yes, what happens if in my local DB (app 'myapp') I have models that have a ForeignKey to User? In other words, my model SomeModel is defined in myapp and should exist in the myapp_db, but it have a ForeignKey to a User in my_auth_db:

class SomeModel(models.model):
    user = models.ForeignKey(User, unique=False, null=False)
    description = models.CharField(max_length=255, null=True)
    dummy = models.CharField(max_length=32, null=True)
    etc.

Second question: Is this possible or is it simply not possible for one DB table to have a ForeignKey to a table in another DB?

If I really wanted to make this work, could I replace the ForeignKey field 'user' with an IntegerField 'user_id' and then if I needed somemodel.user I would instead get somemodel.user_id and use models.User.objects.get(pk=somemodel.user_id), where the router knows to query auth_db for the User? Is this a viable approach?

Upvotes: 3

Views: 4807

Answers (1)

masterfloda
masterfloda

Reputation: 3038

The answer to question 1 is: Yes.

What you will need in any case is a database router (The example in the Django docs is exactly about the auth app, so there's no need to copy this code here).

The answer to question 2 is: Maybe. Not officially. It depends on how you have set up MySQL:

https://docs.djangoproject.com/en/dev/topics/db/multi-db/#limitations-of-multiple-databases

Django doesn’t currently provide any support for foreign key or many-to-many relationships spanning multiple databases.

This is because of referential integrity.

However, if you’re using SQLite or MySQL with MyISAM tables, there is no enforced referential integrity; as a result, you may be able to ‘fake’ cross database foreign keys. However, this configuration is not officially supported by Django.

I have a setup with several legacy MySQL DBs (readonly). This answer shows How to use django models with foreign keys in different DBs?

I later ran into troubles with Django ManyToMany through with multiple databases and the solution (as stated in the accepted answer there) is to set the table name with quotes:

class Meta:    
    db_table = '`%s`.`table2`' % db2_name

Related questions that might provide some additional information:

How to work around lack of support for foreign keys across databases in Django

How to use django models with foreign keys in different DBs?

It would be nice if somebody would take all this information and put in into the official Django doc :-)

Upvotes: 5

Related Questions