Python 检查挂起的 Django 迁移
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31838882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check for pending Django migrations
提问by Moss Collum
In Django, is there an easy way to check whether all database migrations have been run? I've found manage.py migrate --list
, which gives me the information I want, but the format isn't very machine readable.
在 Django 中,是否有一种简单的方法来检查是否所有数据库迁移都已运行?我发现manage.py migrate --list
,它给了我我想要的信息,但格式不是很机器可读。
For context: I have a script that shouldn't start running until the database has been migrated. For various reasons, it would be tricky to send a signal from the process that's running the migrations. So I'd like to have my script periodically check the database to see if all the migrations have run.
对于上下文:我有一个脚本,在迁移数据库之前不应开始运行。由于各种原因,从运行迁移的进程发送信号会很棘手。所以我想让我的脚本定期检查数据库以查看是否所有迁移都已运行。
回答by Ernest Ten
Shell
贝壳
The only simple solution I've found so far is running
到目前为止我发现的唯一简单的解决方案是运行
./manage.py showmigrations | grep '\[ \]'
which will output an empty string in case all migrations have been applied.
如果已应用所有迁移,它将输出一个空字符串。
However, it is closely tied to the output format.
但是,它与输出格式密切相关。
Python
Python
I checked the source code of migrate
command and it seems like this should do the trick:
我检查了migrate
命令的源代码,看起来这应该可以解决问题:
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 not executor.migration_plan(targets)
# Usage example.
if is_database_synchronized(DEFAULT_DB_ALIAS):
# All migrations have been applied.
pass
else:
# Unapplied migrations found.
pass
回答by Parag Tyagi -morpheus-
Using @Ernest code, I've written a manage_custom.py
for pending migrations. You can get the list of pending migrationsalso migratethose pending migrations (only), hence saving your time.
使用@Ernest 代码,我manage_custom.py
为挂起的迁移编写了一个。您可以获得挂起的迁移列表,也可以迁移那些挂起的迁移(仅限),从而节省您的时间。
manage_custom.py
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()
Usage:
用法:
# 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: Please setup environment as per your project structure.
PS:请根据您的项目结构设置环境。
回答by Parag Tyagi -morpheus-
Try,
尝试,
python manage.py migrate --list | grep "\[ \]\|^[a-z]" | grep "[ ]" -B 1
returns,
返回,
<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
Update:
更新:
If you have updated Django version >= 1.11
, use below command,
如果您已更新 Django 版本 >= 1.11
,请使用以下命令,
python manage.py showmigrations | grep '\[ \]\|^[a-z]' | grep '[ ]' -B 1
回答by minusf
1.10 release notes:
1.10 发行说明:
The new
makemigrations --check
option makes the command exit with a non-zero status when model changes without migrations are detected.
makemigrations --check
当检测到没有迁移的模型更改时,新选项使命令以非零状态退出。
If you don't want to create the migrations, combine it with --dry-run
:
如果您不想创建迁移,请将其与--dry-run
:
python manage.py makemigrations --check --dry-run
Note that this doesn't check whether the migrations were applied, it only checks whether the migration files were created.
请注意,这不会检查是否应用了迁移,它只会检查是否创建了迁移文件。
回答by Jan Kyu Peblik
./manage.py showmigrations
#check which already-made migrations have been applied or not
(or: ./manage.py showmigrations someApp
#for specific app alone)
./manage.py showmigrations
#检查哪些已经进行的迁移已被应用
(或:./manage.py showmigrations someApp
#仅针对特定应用程序)
./manage.py makemigrations --dry-run
#check for migrations to be made
(or: ./manage.py makemigrations someApp --dry-run
#for specific app alone)
./manage.py makemigrations --dry-run
#检查要进行的迁移
(或:./manage.py makemigrations someApp --dry-run
#仅针对特定应用程序)
./manage.py makemigrations
#make the migrations
(or: ./manage.py makemigrations someApp
#for specific app alone)
./manage.py makemigrations
#make the migrations
(or: ./manage.py makemigrations someApp
#for specific app only)
./manage.py showmigrations
#check which already-made migrations have been applied or not
(or: ./manage.py showmigrations someApp
#for specific app alone)
./manage.py showmigrations
#检查哪些已经进行的迁移已被应用
(或:./manage.py showmigrations someApp
#仅针对特定应用程序)
./manage.py sqlmigrate someApp 0001
#view SQL changes for specific app & migration
./manage.py sqlmigrate someApp 0001
#查看特定应用程序和迁移的 SQL 更改
./manage.py migrate
#apply migrations
(or: ./manage.py migrate someApp
#for specific app alone)
./manage.py migrate
#apply 迁移
(或:./manage.py migrate someApp
#仅针对特定应用程序)
./manage.py showmigrations
#check which already-made migrations have been applied or not
(or: ./manage.py showmigrations someApp
#for specific app alone)
./manage.py showmigrations
#检查哪些已经进行的迁移已被应用
(或:./manage.py showmigrations someApp
#仅针对特定应用程序)
./manage.py makemigrations --dry-run
#check for migrations to be made
(or: ./manage.py makemigrations someApp --dry-run
#for specific app alone)
./manage.py makemigrations --dry-run
#检查要进行的迁移
(或:./manage.py makemigrations someApp --dry-run
#仅针对特定应用程序)
PS:./manage.py migrate someApp zero
#unapply all migrations for specific app
PS:./manage.py migrate someApp zero
#unapply 特定应用程序的所有迁移
回答by chsymann
Here is my Python soloution to get some information about the migration-states:
这是我的 Python 解决方案,用于获取有关迁移状态的一些信息:
from io import StringIO # for Python 2 use from StringIO import StringIO
from django.core.management import call_command
def get_migration_state():
result = []
out = StringIO()
call_command('showmigrations', format="plan", stdout=out)
out.seek(0)
for line in out.readlines():
status, name = line.rsplit(' ', 1)
result.append((status.strip() == '[X]', name.strip()))
return result
The result of this function looks like that:
此函数的结果如下所示:
[(True, 'contenttypes.0001_initial'),
(True, 'auth.0001_initial'),
(False, 'admin.0001_initial'),
(False, 'admin.0002_logentry_remove_auto_add')]
Maybe it helps some of you guys..
也许它对你们中的一些人有帮助..
回答by Ryabchenko Alexander
I checked it by looking up the table django_migrations
, which stores all applied migrations.
我通过查找django_migrations
存储所有应用迁移的表来检查它。