2017-07-21 12 views
2

Djangoの新機能です。私はDBとしてMySQLを使用していますが、私は、各アプリが異なるスキーマを使用する必要があることを望む異なるデータベースに保存されたDjangoモデル

python3 manage.py startapp app1 
python3 manage.py startapp app1 

: は、私は私のプロジェクトで作成した2つのアプリを持っています。

私はここで説明する手順に従ってみてください: Sharing (mysql) database between apps Django with Database routers

のでsettings.pyに、私は2つのMySQLのスキーマを定義し、デフォルトのスキーマを保持し、 DATABASE_ROUTERSを追加します。

INSTALLED_APPS = [ 
    'django.contrib.admin', 
    'django.contrib.auth', 
    'django.contrib.contenttypes', 
    'django.contrib.sessions', 
    'django.contrib.messages', 
    'django.contrib.staticfiles', 
    'app1', 
    'app2', 
] 

DATABASES = { 
    'default': { 
     'ENGINE': 'django.db.backends.sqlite3', 
     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 
    }, 
    'mydb1':{ 
     'ENGINE': 'django.db.backends.mysql', 
     'NAME': 'APP1DB', 
     'USER': 'user1', 
     'PASSWORD': '****', 
     'HOST': 'localhost', # Or an IP Address that your DB is hosted on 
     'PORT': '3306', 
    }, 
    'mydb2':{ 
     'ENGINE': 'django.db.backends.mysql', 
     'NAME': 'APP2DB', 
     'USER': 'user1', 
     'PASSWORD': '****', 
     'HOST': 'localhost', # Or an IP Address that your DB is hosted on 
     'PORT': '3306', 
    }, 
} 

DATABASE_ROUTERS = ['app1.dbRouter.App1DBRouter', 'app2.dbRouter.App2DBRouter'] 

追加ファイル: APP1/models1.py

from django.db import models 

# Create your models here. 

class Model1(models.Model): 
    name = models.CharField(max_length=100) 

APP2/models2.py

from django.db import models 

# Create your models here. 

class Model2(models.Model): 
    name = models.CharField(max_length=100) 

とファイル: APP1/dbRouter.py

class App1DBRouter(object): 

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

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

    def allow_relation(self,obj1, obj2, **hints): 
     if obj1._meta.app_label == 'app1' and \ 
      obj2._meta.app_label == 'app1': 
      return True 
     return None 

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

APP2/dbRouter.py:この後

class App2DBRouter(object): 

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

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

    def allow_relation(self,obj1, obj2, **hints): 
     if obj1._meta.app_label == 'app2' and \ 
      obj2._meta.app_label == 'app2': 
      return True 
     return None 

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

私は、コマンドのmakemigrationsを実行して、移行したときに、私は2つの異なるスキーマに2つの異なるテーブルになるだろうことを期待? ので:

$ python3 manage.py makemigrations 
Migrations for 'app1': 
    app1/migrations/0001_initial.py 
    - Create model Model1 
Migrations for 'app2': 
    app2/migrations/0001_initial.py 
    - Create model Model2 


$ python3 manage.py migrate 
Operations to perform: 
    Apply all migrations: admin, app1, app2, auth, contenttypes, sessions 
Running migrations: 
    Applying contenttypes.0001_initial... OK 
    ... 
    Applying sessions.0001_initial... OK 

しかし、両方のスキーマでdjango_migrations除いて作成した表がありません。
私はコマンドを使用する場合は、次の両方のモデル表がAPP1DBに作成され

$ python3 manage.py migrate --database=mydb1 

mysql> SHOW TABLES; 
+----------------------------+ 
| Tables_in_APP1DB   | 
+----------------------------+ 
| app1_model1    | 
| app2_model2    | 
| auth_group     | 

これを解決するにはどうすればよいですか?

答えて

2

the documentationによると、特定の移行を実行する必要があるかどうかを判断するために、データベースルータはallow_migrate(db, app_label, model_name=None, **hints)メソッドを実装できます。お使いのルータが、それは単にそのための方法の終わりにTrueを返し、そのような方法を定義するために要求された移行を適用していないので

def allow_migrate(self, db, app_label, **hints): 
    for router in self.routers: 
     try: 
      method = router.allow_migrate 
     except AttributeError: 
      # If the router doesn't have a method, skip to the next one. 
      continue 
     [...] 
    return True 

:カスタムデータベースルーターの方法は、常にデフォルトのデータベース・ルータdjango.db.routerを介して起動されています指定されたデータベース

あなたは、このメソッドを定義することによって、異なるデータベース間でのアプリケーションの分離を実現することができますapp2ための同様

class App1DBRouter(object): 
    [...] 
    def allow_migrate(self, db, app_label, model_name=None, **hints): 
     if app_label == 'app1': 
      return db == 'mydb1' 
     return None 

とします。

+0

完全に動作させるには 1.)クラス名はApp1DBRouterである必要があります 2。)返されるdb == 'mydb1' – aeliv002

+0

@ aeliv002ありがとう、承認されました。コードは構想的でしたが、あなたはアイディアを得ました:-) –

関連する問題