大家好 我将尝试尽可能清楚地解释我的问题,如果您不明白我的意思,请随时问我更精确的问题并原谅我的错误,英语不是我的母语。 我的目标 我想再次开始使用迁移,因为我需要创建一个新表,一年后我公司的开发人员通过直接从 phpmyadmin 创建/删除/更新表绕过它们。 你必须知道的事情 上次迁移是 ...
提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
自从几年前开始使用该框架以来,我经历了很多涉及 Django 迁移的帖子/文章/试错,所以我决定发布一个自我回答的问题,说明完成清理的正确方法重置生产数据库中的迁移,使您拥有与您离开时相同的数据库结构,但重新开始初始迁移。
总的来说,问题是这样的:
当您有一个更大的项目时,您开始为使用 Django 构建的系统积累大量迁移。 这通常不是问题,但是当您开始累积超过 50-100 个迁移文件(其中很多是相同字段的添加和删除)时,最好有一个“清理”选项,因为它应该是众所周知,如果您错误地更改迁移历史记录,您将留下一个或多或少冻结在以前的数据库 state 中的系统,其中解决问题的唯一方法是手动基于 sql 的迁移更改。
我为这个问题提出的解决方案是分步骤的:
第 1 步创建迁移以删除您想要的任何模型或字段并在本地运行它们,您的开发系统必须与所有其他开发人员系统以及生产系统同步......如果不是这种情况,您需要确保它是!
第2步
运行调用python manage.py delete_local_migration_files
(如果你这样命名的话)
import os
import django.apps
from django.conf import settings
from django.core.management.base import BaseCommand
def delete_migrations(app):
print(f"Deleting {app}'s migration files")
migrations_dir = os.path.join(settings.BASE_DIR, f'apps{os.path.sep}{app}{os.path.sep}migrations')
if os.path.exists(migrations_dir):
for the_file in os.listdir(migrations_dir):
file_path = os.path.join(migrations_dir, the_file)
try:
if os.path.isfile(file_path):
os.unlink(file_path)
except Exception as e:
print(e)
f = open(f"{os.path.join(migrations_dir, '__init__.py')}", "w")
f.close()
else:
print('-' * 20, migrations_dir, 'does not exist')
class Command(BaseCommand):
"""
Resets migrations and clears directories
"""
help = 'reset migrations'
def handle(self, *args, **options):
set_of_apps = set()
disregard = []
# get all apps
for model in django.apps.apps.get_models():
if model._meta.app_label not in disregard:
set_of_apps.add(model._meta.app_label)
for app in set_of_apps:
delete_migrations(app)
第 3 步
运行调用python manage.py delete_migrations_from_db
(如果你这样命名的话)
import os
import psycopg2
from django.conf import settings
from django.core.management import call_command
from django.core.management.base import BaseCommand
from django.db import connections
class Command(BaseCommand):
help = 'Migrate on every database in settings.py'
def handle(self, *args, **options):
db_list = settings.DATABASES
# del db_list['default']
for db, _ in db_list.items():
# we have the db name, now lets remove the migration tables in each
try:
host = os.environ['_HOST']
user = os.environ['_USER']
port = os.environ['_PORT']
password = os.environ['_PASSWORD']
conn_str = f"host={host} port={port} user={user} password={password}"
conn = psycopg2.connect(conn_str)
conn.autocommit = True
with connections[db].cursor() as cursor:
delete_statement = 'DELETE from public.django_migrations'
cursor.execute(delete_statement)
print(f'Migration table cleared: {db}')
except psycopg2.Error as ex:
raise SystemExit(f'Error: {ex}')
print('Done!')
步骤 4调用python manage.py makemigrations
重新初始化初始迁移文件
步骤 5调用python manage.py migrate --database=[YourDB] --fake
重新初始化初始迁移文件。 --fake
参数允许在数据库中恢复历史记录时不更改数据库结构(如果您想要一个简单的命令在所有数据库中运行此迁移命令,您可以使用类似下面的代码)
使用python manage.py migrate_all --fake
调用(取决于命名)
from django.conf import settings
from django.core.management import call_command
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = 'Migrate on every database in settings.py'
def add_arguments(self, parser):
parser.add_argument(
'--fake',
action='store_true',
help='fake migrations',
)
def handle(self, *args, **options):
db_list = settings.DATABASES
for db, _ in db_list.items():
self.stdout.write('Migrating database {}'.format(db))
if options['fake']:
call_command('migrate', '--fake', database=db)
else:
# no fake, call regularly
call_command('migrate', database=db)
self.stdout.write('Done!')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.