문제

Recently I downloaded the django_messages app (a private user to user messaging django app) and added it to my django project.

settings.py

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'mydjangoapp.mydjangoappdb',
    'tastypie',
    'gunicorn',
    'south',
    'relationships',
    'pyapns',
    'django_messages',

The app works great and plays well with Django. However for features such as messaging, the database can get quite large. I decided to create a dedicated database to store all the django_messages data.

settings.py

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'django_db',                      
    'USER': 'django_login',                      
    'PASSWORD': 'xxxx',                  
    'HOST': '',                     
    'PORT': '',                      
},
'message_db': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',  
    'NAME': 'django_messagedb',                      
    'USER': 'django_login',                      
    'PASSWORD': 'xxxx',                 
    'HOST': 'XX.XXX.XX.XXX',                     
    'PORT': '5432', 
}

DATABASE_ROUTERS = ['mydjangoapp.messagerouter.MessageRouter']      

And just for clarification, here is my messagerouter.py

class MessageRouter(object):
"""
A custom router written by Riegie to 
control all database operations on models in the 
django_messages application
"""
     def db_for_read(self, model, **hints):
         """
         Attempts to read django_messages models go to
         message_db.
         """
         if model._meta.app_label == 'django_messages':
             return 'message_db'
         return None

     def db_for_write(self, model, **hints):
         """
         Attempts to write django_messages models to go to
         message_db.
         """
         if model._meta.app_label == 'django_messages':
             return 'message_db'
         return None

     def allow_relation(self, obj1, obj2, **hints):
         """
         Allow relations if a model in the django_messages.
         """
         if obj1._meta.app_label == 'django_messages' or \
         obj2._meta.app_label == 'django_messages':
             return True
         return None

     def allow_syncdb(self, db, model):
         """  
         Make sure the django_messages app only appears in the
         'message_db" database.
         """
         if db == 'message_db':
             return model._meta.app_label == 'django_messages'
         elif model._meta.app_label == 'django_messages':
             return False
         return None 

As you can see, I have two databases, one on the local machine on which Django is running and another database on a remote machine. Out of the box, upon installation, django_messages naturally creates tables on the default database. However, I would like it to create tables only on the "message_db" database.

I've looked into the Multi-db Setup Django documentation, but it goes into specifics about Master/Slave configuration. I used the Auth Router example and created the messagerouter.py. Everything syncs up and I get no errors.

enter image description here

When I check the remote database however, the table isn't there! Why is that? Is it because it is not possible to have a remote foreign key table relationship to the Django User?


UPDATE

So I managed to sync the Django_messages app to the other database using the following command: ./manage.py syncdb --database=message_db. This is great. However when I access the app from the Django admin page, I am given the following error:

DatabaseError at /admin/django_messages/message/

relation "django_messages_message" does not exist
LINE 1: SELECT COUNT(*) FROM "django_messages_message"

I find this error odd because I can see the table on the other server through pgadmin III. So the syncing has worked correctly, but now it seems Django can't recognize that table. Am I doing something wrong with my messagerouter.py perhaps?

도움이 되었습니까?

해결책

So after doing a lot of research, I finally came across this, I wish I had seen it earlier. Django doesn't support cross-database relations: https://docs.djangoproject.com/en/dev/topics/db/multi-db/#no-cross-database-relations

As it states: 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.

If you’re using Postgres, Oracle, or MySQL with InnoDB, this is enforced at the database integrity level – database level key constraints prevent the creation of relations that can’t be validated.

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.

Hope this answer saves many of you the trouble.

다른 팁

I've also found this Django patch: https://code.djangoproject.com/attachment/ticket/17875/foreignkey-db-using.patch this might help for cross database relationships

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top