You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何保护Django中单个Customer模型实例(数据库行)不被删除?

解决方案:通过PostgreSQL触发器保护指定Customer记录

核心思路

直接在数据库层面添加触发器,拦截对account='INTERNAL'的Customer记录的删除操作——不管是通过Django ORM、直接SQL还是其他工具操作,都没法删掉这条数据,同时完全不影响其他客户的正常删除逻辑,也不用把所有查询都改成get_or_create。

实现步骤(Django迁移方式)

1. 创建空迁移文件

在你的Customer模型所在的Django app目录下执行:

python manage.py makemigrations --empty 你的app名称

把你的app名称替换成实际的app名(比如customers)。

2. 编写迁移代码

打开生成的空迁移文件,替换成以下内容:

from django.db import migrations

def create_protect_trigger(apps, schema_editor):
    # 定义触发器函数:拦截INTERNAL客户的删除请求
    trigger_func_sql = """
    CREATE OR REPLACE FUNCTION protect_internal_customer()
    RETURNS TRIGGER AS $$
    BEGIN
        IF OLD.account = 'INTERNAL' THEN
            RAISE EXCEPTION '禁止删除内部客户占位记录';
        END IF;
        RETURN OLD;
    END;
    $$ LANGUAGE plpgsql;
    """
    # 绑定触发器到Customer表的DELETE操作
    trigger_sql = """
    CREATE TRIGGER prevent_internal_customer_delete
    BEFORE DELETE ON 你的app名称_customer
    FOR EACH ROW
    EXECUTE FUNCTION protect_internal_customer();
    """
    # 执行SQL语句
    schema_editor.execute(trigger_func_sql)
    schema_editor.execute(trigger_sql)

def drop_protect_trigger(apps, schema_editor):
    # 回滚迁移时清理触发器和函数
    schema_editor.execute("DROP TRIGGER IF EXISTS prevent_internal_customer_delete ON 你的app名称_customer;")
    schema_editor.execute("DROP FUNCTION IF EXISTS protect_internal_customer();")

class Migration(migrations.Migration):
    dependencies = [
        # 替换成你当前app的上一个迁移编号,比如('customers', '0003_add_phone_field')
        ('你的app名称', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(create_protect_trigger, drop_protect_trigger),
    ]

注意:

  • 把代码中所有你的app名称替换为实际的app名称
  • 确保dependencies里的迁移编号和你当前app的最新迁移一致

3. 执行迁移

运行以下命令生效:

python manage.py migrate

验证效果

  • 尝试删除内部客户:不管用Customer.objects.get(account='INTERNAL').delete()还是直接执行SQL,都会抛出异常,阻止删除
  • 其他普通客户可以正常删除,完全不受影响

补充说明

这种方式比get_or_create更可靠——从数据库底层彻底锁死了删除操作,不会出现误删后再恢复的情况,也不用修改任何现有业务代码的查询逻辑,完美兼容外键的原有删除规则(比如其他客户的外键关联可以正常CASCADE或SET_NULL)

内容的提问来源于stack exchange,提问作者nigel222

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 07:26:13