2015-08-05 20 views
15

Czy w Django można sprawdzić, czy wszystkie migracje bazy danych zostały uruchomione? Znalazłem manage.py migrate --list, co daje mi informacje, których potrzebuję, ale format nie jest odczytywalny maszynowo.Sprawdź oczekujące migracje Django

Dla kontekstu: Mam skrypt, który nie powinien się uruchamiać, dopóki nie zostanie migrowana baza danych. Z różnych powodów wysyłanie sygnału z procesu, który uruchamia migracje, byłoby trudne. Dlatego chciałbym, aby mój skrypt okresowo sprawdzał bazę danych, aby sprawdzić, czy wszystkie migracje zostały uruchomione.

+0

Czy używasz automatycznego skryptu do sprawdzania migracji jak tkanina? – Praneeth

+1

http://stackoverflow.com/a/8491203/4325513 – Praneeth

Odpowiedz

20

Shell

Jedyne proste rozwiązanie znalazłem dotąd działa

./manage.py showmigrations | grep '\[ \]' 

który wyświetli pusty ciąg w przypadku wszystkie migracje zostały zastosowane.

Jednak jest ściśle związany z formatem wyjściowym.

Python

Sprawdziłem kod źródłowy dowodzenia migrate i wydaje się, że to powinno załatwić sprawę:

from django.db.migrations.executor import MigrationExecutor 
from django.db import connections, DEFAULT_DB_ALIAS 


def is_database_synchronized(database): 
    connection = connections[database] 
    connection.prepare_database() 
    executor = MigrationExecutor(connection) 
    targets = executor.loader.graph.leaf_nodes() 
    return False if executor.migration_plan(targets) else True 

# Usage example. 
if is_database_synchronized(DEFAULT_DB_ALIAS): 
    # All migrations have been applied. 
    pass 
else: 
    # Unapplied migrations found. 
    pass 
+2

W Django 1.7 lub w górę, można użyć: './manage showmigrations --list' lub ' ./manage showmigrations --plan' – NeoMorfeo

2

Korzystanie @Ernest kodu Napisałem manage_custom.py dla toczących migracje . Możesz uzyskać listę oczekujących migracji również migrować tych oczekujących migracji (tylko), co pozwala zaoszczędzić czas.

manage_custom.py

__author__ = "Parag Tyagi" 

# set environment 
import os 
import sys 
import django 
sys.path.append('../') 
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') 
django.setup() 

from django.core.management import execute_from_command_line 
from django.db import DEFAULT_DB_ALIAS, connections 
from django.db.migrations.executor import MigrationExecutor 


class Migration(object): 
    """ 
    A custom manage.py file for managing pending migrations (only) 
    """ 

    def __init__(self, migrate_per_migration_id=False): 
     """ 
     :param migrate_per_migration_id: Setting this to `True` will migrate each pending migration of any 
     particular app individually. `False` will migrate the whole app at a time. 

     You can add more arguments (viz. showmigrations, migrate) by defining the argument with prefix as 'ARGV_' 
     and create its functionality accordingly. 
     """ 
     self.ARG_PREFIX = 'ARGV_' 
     self.MIGRATE_PER_MIGRATION_ID = migrate_per_migration_id 
     self.ARGV_showmigrations = False 
     self.ARGV_migrate = False 

    @staticmethod 
    def get_pending_migrations(database): 
     """ 
     :param database: Database alias 
     :return: List of pending migrations 
     """ 
     connection = connections[database] 
     connection.prepare_database() 
     executor = MigrationExecutor(connection) 
     targets = executor.loader.graph.leaf_nodes() 
     return executor.migration_plan(targets) 

    def check_arguments(self, args): 
     """ 
     Method for checking arguments passed while running the command 
     :param args: Dictionary of arguments passed while running the script file 
     :return: Set the argument variable ('ARGV_<argument>') to True if found else terminate the script 
     """ 
     required_args = filter(None, [var.split(self.ARG_PREFIX)[1] if var.startswith(self.ARG_PREFIX) 
             else None for var in self.__dict__.keys()]) 
     if any(k in args for k in required_args): 
      for arg in required_args: 
       if arg in args: 
        setattr(self, '{}{}'.format(self.ARG_PREFIX, arg), True) 
        break 
     else: 
      print ("Please pass argument: {}" 
        "\ne.g. python manage_custom.py {}".format(required_args, required_args[0])) 
      sys.exit() 

    def do_migration(self): 
     """ 
     Migrates all the pending migrations (if any) 
     """ 
     pending_migrations = self.get_pending_migrations(DEFAULT_DB_ALIAS) 
     if pending_migrations: 
      done_app = [] 
      for mig in pending_migrations: 
       app, migration_id = str(mig[0]).split('.') 
       commands = ['manage.py', 'migrate'] + ([app, migration_id] if self.MIGRATE_PER_MIGRATION_ID else [app]) 
       if self.ARGV_migrate and (app not in done_app or self.MIGRATE_PER_MIGRATION_ID): 
        execute_from_command_line(commands) 
        done_app.append(app) 
       elif self.ARGV_showmigrations: 
        print (str(mig[0])) 
     else: 
      print ("No pending migrations") 


if __name__ == '__main__': 
    args = sys.argv 
    migration = Migration() 
    migration.check_arguments(args) 
    migration.do_migration() 

Zastosowanie:

# below command will show all pending migrations 
python manage_custom.py showmigrations 

# below command will migrate all pending migrations 
python manage_custom.py migrate 

PS: Proszę środowisko konfiguracji jak na swoje struktury projektu.

6

spróbować

python manage.py migrate --list | grep "\[ \]\|^[a-z]" | grep "[ ]" -B 1 

powraca,

<app_1> 
[ ] 0001_initial 
[ ] 0002_auto_01201244 
[ ] 0003_auto_12334333 

<app_2> 
[ ] 0031_auto_12344544 
[ ] 0032_auto_45456767 
[ ] 0033_auto_23346566 

<app_3> 
[ ] 0008_auto_3446677 


Aktualizacja:

Jeśli aktualizowany Django do 1.11, skorzystaj z poniższego polecenia,

python manage.py showmigrations | grep '\[ \]\|^[a-z]' | grep '[ ]' -B 1 
0

1,10 wydaniu:

Nowy makemigrations --check opcja sprawia, że ​​wyjście polecenia z niezerowym momencie wykrycia zmiany modelu bez migracji.

Powiązane problemy