在Django中,是否有一种简单的方法可以检查是否已运行所有数据库迁移?我找到了manage.py migrate --list
,它为我提供了我想要的信息,但格式并非机器可读。
对于上下文:我有一个脚本,在迁移数据库之前不应该开始运行。由于各种原因,从运行迁移的进程发送信号会很棘手。因此,我希望让我的脚本定期检查数据库,看看是否所有迁移都已运行。
答案 0 :(得分:40)
<强>贝壳
我到目前为止找到的唯一简单解决方案是
./manage.py showmigrations | grep '\[ \]'
如果已应用所有迁移,将输出空字符串。
但是,它与输出格式密切相关。
<强>的Python
我检查了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 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
答案 1 :(得分:13)
1.10发行说明:
当检测到没有迁移的模型更改时,新的
makemigrations --check
选项使命令以非零状态退出。
答案 2 :(得分:11)
尝试,
python manage.py migrate --list | grep "\[ \]\|^[a-z]" | grep "[ ]" -B 1
返回,
<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
的更新:
如果您更新了Django版本&gt; = 1.11
,请使用以下命令,
python manage.py showmigrations | grep '\[ \]\|^[a-z]' | grep '[ ]' -B 1
答案 3 :(得分:6)
./manage.py showmigrations
#check已经应用了哪些已经进行的迁移
(或./manage.py showmigrations someApp
#仅针对特定应用
./manage.py makemigrations --dry-run
#check进行迁移
(或./manage.py makemigrations someApp --dry-run
#仅针对特定应用
./manage.py makemigrations
#make the migrations
(或./manage.py makemigrations someApp
#仅针对特定应用
./manage.py showmigrations
#check已经应用了哪些已经进行的迁移
(或./manage.py showmigrations someApp
#仅针对特定应用
./manage.py sqlmigrate someApp 0001
#view特定应用的SQL更改&amp;迁移
./manage.py migrate
#apply迁移
(或./manage.py migrate someApp
#仅针对特定应用
./manage.py showmigrations
#check已经应用了哪些已经进行的迁移
(或./manage.py showmigrations someApp
#仅针对特定应用
./manage.py makemigrations --dry-run
#check进行迁移
(或./manage.py makemigrations someApp --dry-run
#仅针对特定应用
PS:
./manage.py migrate someApp zero
#unapply特定应用的所有迁移
答案 4 :(得分:2)
使用@Ernest代码,我为待定迁移编写了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()
<强>用法:
# 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 :请根据您的项目结构设置环境。
答案 5 :(得分:2)
3.1发行说明
新的migration --check选项可在检测到未应用的迁移时使命令以非零状态退出。
https://docs.djangoproject.com/en/3.1/ref/django-admin/#cmdoption-migrate-check
所以最后我们可以
python manage.py migrate --check
答案 6 :(得分:0)
这是我的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
此函数的结果如下:
[(True, 'contenttypes.0001_initial'),
(True, 'auth.0001_initial'),
(False, 'admin.0001_initial'),
(False, 'admin.0002_logentry_remove_auto_add')]
也许对某些人有帮助。
答案 7 :(得分:0)
我通过查看表django_migrations
上的数据库来进行检查,以存储所有已应用的迁移