Django 2.2迁移删除auth_permission行无效,求排查原因
这个现象的核心原因很明确:你的迁移确实执行了删除操作,但在整个migrate流程结束后,Django自动触发的权限重建机制又把你删掉的权限重新创建了回来,而ID更新正是因为这是全新生成的数据库记录。
为什么会这样?
Django在每次执行完所有迁移任务后,会发送post_migrate信号,而django.contrib.auth模块中的create_permissions函数会监听这个信号。它的作用是检查所有已注册模型的权限配置:如果发现某个模型对应的权限不存在(不管是被手动删除了还是从未创建过),就会自动重新生成这些权限。
你的迁移是在migrate过程中执行删除,但后续的post_migrate信号触发的操作,又把这些权限重新添加回了auth_permission表——这就是为什么你看到迁移显示[OK],但权限依然存在,甚至ID还变了。
而在shell_plus中删除时,并没有触发post_migrate信号,所以删除操作不会被后续的自动重建覆盖,自然能生效。
解决办法
根据你的实际场景,有两种常用的解决方案:
方案1:修改模型配置,阻止权限自动生成
如果这些权限是你在自定义模型的Meta类中声明的自定义权限,直接从模型配置里移除它们即可:
# 你的模型文件,比如models.py from django.db import models class YourModel(models.Model): # 模型字段... class Meta: # 移除不需要的权限声明 permissions = [ # 删掉 ('do_x', 'Can do X') 和 ('do_y', 'Can do Y') # 保留其他需要的权限 ]
然后重新执行迁移,Django就不会再自动生成这些权限了,你之前的删除迁移也能彻底生效。
方案2:通过post_migrate信号在权限重建后删除
如果这些权限是Django为默认模型生成的(或者你无法修改模型配置),可以通过监听post_migrate信号,在权限自动重建完成后再执行一次删除操作:
- 在你的app的
apps.py中添加信号处理逻辑:
from django.apps import AppConfig from django.db.models.signals import post_migrate from django.contrib.auth.models import Permission from django.db.models import Q def remove_unwanted_permissions(sender, **kwargs): # 在权限重建完成后,删除指定权限 Permission.objects.filter(Q(name='Can do X') | Q(name='Can do Y')).delete() class AbcAppConfig(AppConfig): name = 'abc' def ready(self): # 绑定信号处理函数 post_migrate.connect(remove_unwanted_permissions, sender=self)
- 在app的
__init__.py中指定默认配置类:
default_app_config = 'abc.apps.AbcAppConfig'
这样每次migrate结束后,都会自动删除那些被Django重建的权限,确保最终的auth_permission表中没有这些记录。
内容的提问来源于stack exchange,提问作者zenprogrammer

