2012-12-21 4 views
4

J'ai essayé d'installer Django 1.4.3 pour utiliser plusieurs DB, mais pour la vie de moi, je ne peux pas le faire fonctionner. J'ai lu la documentation et les messages sur le SO, et fait ce qui suit:Comment utiliser le routeur DB dans Django 1.4

1) Ajouter une seconde configuration de DB dans settings.py, comme suit:

DATABASES = { 
    'default': { 
     'ENGINE': 'django.db.backends.sqlite3', 
     'NAME': '/tmp/django.db', 
     'USER': '', 
     'PASSWORD': '', 
     'HOST': '', 
     'PORT': '', 
    }, 
    'db1' : { 
     'ENGINE': 'django.db.backends.mysql', 
     'NAME': 'db1', 
     'USER': 'fake', 
     'PASSWORD': 'fake', 
     'HOST': 'fake.host.com', 
     'PORT': '3306', 
    }, 
} 

2) Créer une routers.py et définir une routeur DB comme suit
(note: Selon SO messages, si vous définissez un routeur DB dans models.py, le routeur ne fonctionnera pas)

class DBRouter(object): 
    def db_for_read(self, model, **hints): 
     return 'db1' 

    def db_for_write(self, model, **hints): 
     return 'db1' 

    def allow_syncdb(self, db, model): 
     return 'db1' 

3) Ajoutez les lignes suivantes à settings.py
(Note: Selon SO messages, ces lignes doivent être après la DATABASES configurations

from django.db import connections 
DATABASE_ROUTERS = ['fakeproject.routers.DBRouter',] 

C'était faux. Ne pas mettre from django.db import connections ici car il empêche le routeur être enregistré

Mes symptômes:
Apparemment, tous mes appels sont acheminés par la valeur par défaut DB. Détails ci-dessous:

  • Les deux fonctionnent de paramètres DB (je peux effectuer manage.py indpectdb --database db1 avec succès cadre

  • DATABASE_ROUTERS ne génère aucun reproche (même si je mets un mauvais chemin au routeur DB, ou même un non objet chaîne)

  • lorsque je tente d'accéder à mes objets via manage.py shell, je peux faire MyModel.objects.all() mais lorsque je tente en fait itérer, je me dit no such table. La valeur par défaut DB ne pas cette table, mais « DB1 » a clairement comme je l'ai généré le modèle en utilisant inspectdb à ce sujet. Pour preuve, si je permute la configuration DB entre db1 et default, je peux accéder à l'objet sans problème.

Toute aide hautement appréciée!

Répondre

2

J'ai découvert que l'instruction de l'étape 3 "from django.db import connections " empêchait l'enregistrement du routeur DB. Lorsque j'ai supprimé cette déclaration, le routeur a été enregistré et les choses ont commencé à fonctionner comme prévu.

1

Je pense que le problème se présente probablement parce que votre routers.py ne renvoie une référence à 'db1' mais comme vous dites que vous ne routé vers 'default' Je ne suis pas sûr (j'attendre qu'il soit le seul acheminé vers 'db1'.

Dans routers.py créez une classe de routeur maître, puis sous-classe pour chaque base de données - et initialisez avec une chaîne app_label afin de pouvoir les différencier.

class MasterRouter(object): 
    def __init__(self, app_label): 
     super(MasterRouter, self).__init__() 
     self.app_label = app_label 

    def db_for_read(self, model, **hints): 
     if model._meta.app_label == self.app_label: 
      return self.app_label 
     return None 

    def db_for_write(self, model, **hints): 
     if model._meta.app_label == self.app_label: 
      return self.app_label 
     return None 

    def allow_relation(self, obj1, obj2, **hints): 
     if obj1._meta.app_label == self.app_label or obj2._meta.app_label == self.app_label: 
      return True 
     return None 

    def allow_syncdb(self, db, model): 
     if db == 'default': 
      return model._meta.app_label == self.app_label 
     elif model._meta.app_label == self.app_label: 
      return False 
     return None 

class DefaultRouter(MasterRouter): 
    def __init__(self): 
     super(DefaultRouter, self).__init__('default') 

class DB1Router(MasterRouter): 
    def __init__(self): 
     super(DB1Router, self).__init__('db1') 

puis dans votre settings.py les routeurs déclarent

DATABASE_ROUTERS = [ 'routers.DefaultRouter', 'routers.DB1Router' ] 

ofcourse, vous aurez probablement envie de mettre en place différemment vos MasterRouter de classe l'emporte.

+0

Merci pour la réponse! Pourquoi aurait une sous-classe entre résoudre le problème si? –

+0

Vous avez besoin de deux classes dans 'DATABASE_ROUTERS' - une pour chaque DB. Je sous-classe comme je préfère le code DRY (vous pourriez réécrire en deux classes, mais le code serait presque identique). – danodonovan