2016-02-24 17 views
8

Mam trudności z tworzeniem migracji danych. Używam dwóch baz danych dla moich aplikacji. Skonfigurowałem bazy danych w settings.py, a także utworzyłem router, jak w Django docs.Migracje Django z wieloma bazami danych

# settings.py 
DB_HOST = 'localhost' 
DATABASES = { 
'default': { 
    'ENGINE': 'django.db.backends.mysql', 
    'NAME': 'helios', 
    'HOST': DB_HOST, 
    'OPTIONS': { 
     'read_default_file': join(dirname(__file__), 'default.cnf'), 
    }, 
}, 
'other': { 
    'ENGINE': 'django.db.backends.mysql', 
    'NAME': 'gala_pol', 
    'HOST': DB_HOST, 
    'OPTIONS': { 
     'read_default_file': join(dirname(__file__), 'other.cnf'), 
    }, 
}, 

DATABASE_APPS_MAPPING = { 
    'contenttypes': 'default', 
    'auth': 'default', 
    'admin': 'default', 
    'sessions': 'default', 
    'messages': 'default', 
    'staticfiles': 'default', 
    'woodsmen': 'default', 
    'helios': 'default', 
    'hush': 'default', 
    'hunt': 'other', 
    'meat': 'other', 
    'beast': 'other', 
} 

# routers.py 

class DatabaseAppsRouter(object): 

    def db_for_read(self, model, **hints): 

     if model._meta.app_label in settings.DATABASE_APPS_MAPPING: 
      return settings.DATABASE_APPS_MAPPING[model._meta.app_label] 
     return None 

    def db_for_write(self, model, **hints): 

     if model._meta.app_label in settings. 
      return settings.DATABASE_APPS_MAPPING[model._meta.app_label] 
     return None 

    def allow_relation(self, obj1, obj2, **hints): 

     db1 = settings.DATABASE_APPS_MAPPING.get(obj1._meta.app_label) 
     db2 = settings.DATABASE_APPS_MAPPING.get(obj2._meta.app_label) 
     if db1 and db2: 
      return db1 == db2 
     return None 

    def allow_migrate(self, db, app_label, model_name=None, **hints): 

     if db in settings.DATABASE_APPS_MAPPING.values(): 
      return settings.DATABASE_APPS_MAPPING.get(app_label) == db 
    elif app_label in settings.DATABASE_APPS_MAPPING: 
      return False 

Oto wzór i migracje jednej z tych aplikacji:

# hunt.models.py 

class Dish(models.Model): 
    """ 
    Investigation case 
    """ 
    display_name = models.CharField(max_length=64, unique=True) 
    department = models.ForeignKey(Kitchen, null=True) 
    case_type = models.PositiveSmallIntegerField(choices=CASE_TYPE_CHOICES, default=DEF_CASE_TYPE) 
    created_at = models.DateTimeField(blank=True, null=True) 
    comment = models.CharField(max_length=256, blank=True, null=True) 

    class Meta: 
     verbose_name = 'case' 
     app_label = 'hunt' 

    def __unicode__(self): 
     return (u'%s (%s)' % (self.display_name, self.created_at)).strip() 


# hunt.migrations.0001_initial.py 

class Migration(migrations.Migration): 

    app_label = 'hunt' 

    dependencies = [ 
    ] 

    operations = [ 
     migrations.CreateModel(
      name='Dish', 
      fields=[ 
       ('id', models.AutoField(verbose_name='ID', auto_created=True, primary_key=True, serialize=False)), 
       ('display_name', models.CharField(max_length=64, unique=True)), 
       ('case_type', models.PositiveSmallIntegerField(default=0, choices=[(0, 'Unknown'), (1, 'General'), (2, 'Terror'), (3, 'Narco'), (4, 'Fraud'), (5, 'Slavery'), (6, 'Traffic'), (7, 'RICO'), (8, 'War'), (9, 'Cyber'), (20, 'Other')])), 
       ('created_at', models.DateTimeField(null=True, blank=True)), 
       ('comment', models.CharField(max_length=256, null=True, blank=True)), 
      ], 
      options={ 
       'verbose_name': 'case', 
      }, 
     ), 
    ] 

# hunt.migrations.0002_add_hunts.py 


def create_initial_hunts(apps, schema_editor): 

    if settings.DEBUG:  
     print('\nContent added') 


class Migration(migrations.Migration): 
    dependencies = [ 
     ('hunt', '0001_initial'), 
    ] 


    operations = [ 
     migrations.RunPython(create_initial_hunts, hints={'schema_editor': 'other'}), 
    ] 

Problemem jest: gdy uruchamiam „migrować” polecenie, tylko aplikacje, które podłączone są do domyślnej bazy danych migracji. Migracje w pozostałych aplikacjach nigdy nie są uruchamiane. Jeśli uruchomię migrację dla takiej aplikacji z opcją --database - działa dobrze.

Jak określić bazę danych dla migracji? Czy router nie powinien dokładnie tego zarządzać? A może przegapiłem coś innego?

Odpowiedz

10

Musisz uruchomić migrate raz dla każdej bazy danych, określając cel za pomocą --database. Za każdym razem, gdy skonsultujesz się z routerem, zobaczysz, które migracje faktycznie wykonują w tej bazie danych.

Zgaduję, że został zaprojektowany w taki sposób, aby faworyzować jawność nad impaktem. Na przykład przepływ pracy może wymagać migracji różnych baz danych w różnym czasie.

Uwaga jednak, że nie będzie w stanie powiedzieć, który z wyjścia migracje były faktycznie wykonywane, since:

migracje będą cicho nie tylko wykonywać żadnych operacji na modelu, dla których ta zwraca False .

+1

Dzięki, skończyłem robić dokładnie to. –

+3

Dlaczego Django nie obsługuje tego problemu z wieloma DB, jeśli oferuje 'DATABASE_ROUTERS'? To jest dziwne. – dannydedog

Powiązane problemy