J'ai du mal à créer des migrations de données. J'utilise deux bases de données pour mes applications. J'ai configuré des bases de données dans settings.py et j'ai également créé un routeur comme dans Django docs .
# 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
Voici le modèle et les migrations de l'une de ces applications:
# 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'}),
]
Le problème est: lorsque j'exécute la commande "migrate", seules les applications connectées à la base de données par défaut sont migrées. Les migrations dans le reste des applications ne sont jamais exécutées. Si je lance la migration pour une telle application avec l'option --database - cela fonctionne très bien.
Comment puis-je spécifier la base de données par migration? Le routeur n'est-il pas censé gérer exactement cela? Ou j'ai raté autre chose?
Vous devez exécuter migrate
une fois pour chaque base de données, en spécifiant la cible avec --database
. Chaque fois, il consultera votre routeur pour voir quelles migrations effectuer réellement sur cette base de données.
Je suppose qu'il a été conçu de cette façon pour favoriser l'explicitation au lieu de l'implicence. Par exemple, votre flux de travail peut vous obliger à migrer les différentes bases de données à différents moments.
Notez, cependant, que vous ne pourrez pas dire à partir de la sortie quelles migrations ont été réellement effectuées, puisque :
Si
allow_migrate()
renvoieFalse
, toutes les opérations de migration pourmodel_name
Seront ignorées en silence lors de l'exécution demigrate
surdb
.