Skip to content

第三站练习答案 ​

返回纵览 | 专题一 | 专题二

python
# 模型增量
from django.core.validators import MaxValueValidator, MinValueValidator

priority = models.PositiveSmallIntegerField(
    default=3,
    validators=[MinValueValidator(1), MaxValueValidator(5)],
)

验证器改善表单和 full_clean() 体验;数据库保证还需要 CheckConstraint(condition=Q(priority__range=(1, 5)), ...)。

python
# 数据迁移函数示意
def set_existing_priority(apps, schema_editor):
    Ticket = apps.get_model("tickets", "Ticket")
    Ticket.objects.filter(priority__isnull=True).update(priority=3)


def unset_priority(apps, schema_editor):
    Ticket = apps.get_model("tickets", "Ticket")
    Ticket.objects.update(priority=None)

迁移中使用 apps.get_model() 获取历史模型,不直接导入当前 tickets.models.Ticket。

bash
python manage.py makemigrations
python manage.py sqlmigrate tickets 0002
python manage.py migrate
python manage.py makemigrations --check --dry-run

专题二核对 ​

  • 新增一个临时布尔列标记“由本次迁移填充”的行,反向迁移只还原这些行;完成兼容窗口后再删除标记列。
  • 百万行回填按主键游标分批,记录末尾主键、耗时、锁等待和失败数;批次可重入并在主从延迟超预算时暂停。
  • 用户模型牵涉外键、M2M 中间表、权限和 ContentType;中途替换需要显式数据搬迁与依赖顺序,不能只重命名表。

深水边界 ​

回滚数据迁移只有在信息仍可恢复时才真实可逆。把多个旧值合并成一个新值后,反向函数无法猜回原值;此时应明确使用前进修复或先保存映射。

开放练习(不提供答案) ​

设计一次将 title 拆成 summary 与 description 的零停机迁移,写出扩展、回填、切换、收缩四个发布批次。

继续第四站

加码题解:约束与数据迁移 ​

python
from django.db import migrations

def fill_currency(apps, schema_editor):
    Order = apps.get_model('orders', 'Order')
    Order.objects.filter(currency__isnull=True).update(currency='CNY')

class Migration(migrations.Migration):
    operations = [migrations.RunPython(fill_currency, migrations.RunPython.noop)]

关键推理 ​

数据迁移使用历史模型,先填充可空字段,再在下一次迁移收紧约束。

可替代方案 ​

大表按主键分批更新并监控复制延迟,避免一次 UPDATE 长时间占锁。

典型错误 ​

在迁移里直接 import 当前 Model,未来模型变化后旧迁移失去可重复性。

复盘时请把状态码/事务/权限/资源清理中的至少一项写成自动化测试,而不是只截图成功页面。

用心记录每一步成长