Files
Django/config/management/commands/recover_config_0006.py

105 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""修复 config.0006 半路失败:去重 + 补唯一约束/索引,然后 fake 0006。"""
from django.core.management.base import BaseCommand
from django.db import connection
from django.db.models import Max
from config.models import PopupPage, Tupianpeizhi
def _table_indexes(table):
with connection.cursor() as cursor:
cursor.execute(f'SHOW INDEX FROM `{table}`')
rows = cursor.fetchall()
# Key_name, Column_name, Non_unique
by_key = {}
for row in rows:
key_name = row[2]
col = row[4]
non_unique = row[1]
by_key.setdefault(key_name, {'cols': [], 'unique': non_unique == 0})
by_key[key_name]['cols'].append(col)
return by_key
def _has_unique_on(table, columns):
cols = list(columns)
for info in _table_indexes(table).values():
if info['unique'] and info['cols'] == cols:
return True
return False
def _drop_index(table, key_name):
with connection.cursor() as cursor:
cursor.execute(f'ALTER TABLE `{table}` DROP INDEX `{key_name}`')
def _add_unique(table, name, columns):
cols = ', '.join(f'`{c}`' for c in columns)
with connection.cursor() as cursor:
cursor.execute(f'ALTER TABLE `{table}` ADD UNIQUE `{name}` ({cols})')
def _add_index(table, name, columns):
cols = ', '.join(f'`{c}`' for c in columns)
with connection.cursor() as cursor:
cursor.execute(f'CREATE INDEX `{name}` ON `{table}` ({cols})')
class Command(BaseCommand):
help = 'config.0006 半路失败时:清重复数据、补约束,再执行 migrate config 0006 --fake'
def handle(self, *args, **options):
self.stdout.write('1) 清理重复数据…')
for row in Tupianpeizhi.objects.values('club_id', 'ImageType').annotate(max_id=Max('id')):
n = Tupianpeizhi.objects.filter(
club_id=row['club_id'],
ImageType=row['ImageType'],
).exclude(id=row['max_id']).delete()[0]
if n:
self.stdout.write(f' tupianpeizhi 删除 {n} 条重复')
for row in PopupPage.objects.values('club_id', 'page_key').annotate(max_id=Max('id')):
n = PopupPage.objects.filter(
club_id=row['club_id'],
page_key=row['page_key'],
).exclude(id=row['max_id']).delete()[0]
if n:
self.stdout.write(f' popup_page 删除 {n} 条重复')
self.stdout.write('2) 检查并补约束/索引…')
# popup_page去掉 page_key 单独唯一,改为 (club_id, page_key)
popup_indexes = _table_indexes('popup_page')
for key_name, info in popup_indexes.items():
if info['unique'] and info['cols'] == ['page_key']:
self.stdout.write(f' 删除 popup_page 旧唯一索引 {key_name}')
_drop_index('popup_page', key_name)
if not _has_unique_on('popup_page', ['club_id', 'page_key']):
self.stdout.write(' 添加 popup_page UNIQUE (club_id, page_key)')
_add_unique('popup_page', 'popup_page_club_page_key_uniq', ['club_id', 'page_key'])
else:
self.stdout.write(' popup_page UNIQUE (club_id, page_key) 已存在')
if not _has_unique_on('tupianpeizhi', ['club_id', 'ImageType']):
self.stdout.write(' 添加 tupianpeizhi UNIQUE (club_id, ImageType)')
_add_unique('tupianpeizhi', 'tupianpeizhi_club_id_ImageType_uniq', ['club_id', 'ImageType'])
else:
self.stdout.write(' tupianpeizhi UNIQUE (club_id, ImageType) 已存在')
lunbo_indexes = _table_indexes('lunbo')
if 'lunbo_club_page_type_idx' not in lunbo_indexes:
self.stdout.write(' 添加 lunbo 索引 lunbo_club_page_type_idx')
_add_index('lunbo', 'lunbo_club_page_type_idx', ['club_id', 'page_key', 'ImageType'])
else:
self.stdout.write(' lunbo 索引 lunbo_club_page_type_idx 已存在')
self.stdout.write(self.style.SUCCESS(
'\n完成。请执行:\n'
' python manage.py migrate config 0006 --fake\n'
' python manage.py migrate config\n'
' python manage.py migrate\n'
))