前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >若依Django框架soft-delete导致的数据查询异常

若依Django框架soft-delete导致的数据查询异常

作者头像
obaby
发布2023-03-24 15:41:06
3320
发布2023-03-24 15:41:06
举报
文章被收录于专栏:obaby@marsobaby@mars
在model中定义一个设备分组:
代码语言:javascript
复制
class DeviceGroup(CoreModel):
    name = models.CharField(blank=False, null=False, max_length=64, help_text='名称')
    dept = models.ForeignKey(Dept, blank=True, null=True, on_delete=models.CASCADE, help_text='部门')
    parent = models.ForeignKey('self', null=True, blank=True, related_name='children', verbose_name='上级分组',
                               on_delete=models.SET_NULL)
    is_root = models.BooleanField(default=False, help_text='是否根目录')
    index = models.IntegerField(default=0, help_text='排序索引')
    function_field = models.JSONField(blank=True, null=True, help_text='默认代码')
    function_text = models.TextField(blank=True, null=True, help_text='默认代码文本')
    is_show = models.BooleanField(default=True, help_text='是否显示')

其中parent定义了自己的上级分组,按照正常的查询逻辑,如果要返回树形结构只需要查询父节点为空的数据遍历下属分组即可,但是在实际的查询中会发现有一些节点显示不出来:

代码语言:javascript
复制
{
    "code": 2000,
    "data": {
        "page": 1,
        "limit": 1,
        "total": 1,
        "data": [
            {
                "id": 25,
                "modifier_name": "超级管理员",
                "creator_name": "超级管理员",
                "create_datetime": "2023-03-22 10:50:45",
                "update_datetime": "2023-03-22 10:50:45",
                "children": [
                    {
                        "id": 26,
                        "children": [],
                        "description": null,
                        "modifier": "2",
                        "dept_belong_id": "1",
                        "update_datetime": "2023-03-22 10:50:57",
                        "create_datetime": "2023-03-22 10:50:57",
                        "is_deleted": false,
                        "name": "123",
                        "is_root": false,
                        "index": 0,
                        "function_field": null,
                        "function_text": null,
                        "is_show": true
                    }
                ],
                "has_children": 1,
                "description": null,
                "modifier": "2",
                "dept_belong_id": "1",
                "is_deleted": false,
                "name": "1223",
                "is_root": false,
                "index": 0,
                "function_field": null,
                "function_text": null,
                "is_show": true
            }
        ]
    },
    "msg": "获取成功"
}

通过后台会发现数据并不是只有这么多:

当时比较好奇的一点是为什么父节点还在但是下面的数据却是空的,由于测试数据名字比较随意,导致想了很久才明白。虽然显示的都是1223但是这个设备分组却有不同的id,并不是同一个id。直接查看数据库会出现很多软删除的数据:

这些数据直接删除是删除不掉的,因为foreignkey约束导致删除失败:

对于这种数据需要在删除的时候断开子分类的关联,或者直接将子分类一并删除,保留子分类可以通过下面的代码删除这些软删除的数据:

代码语言:javascript
复制
def clear_delete_data():
    dgs = DeviceGroup.objects.filter(is_deleted=True)
    for d in dgs:
        DeviceGroup.objects.filter(parent =d).update(parent =None)
        d.delete()

删除之后重新拉取数据:

代码语言:javascript
复制
{
    "code": 2000,
    "data": {
        "page": 1,
        "limit": 1,
        "total": 3,
        "data": [
            {
                "id": 16,
                "modifier_name": "超级管理员",
                "creator_name": "超级管理员",
                "create_datetime": "2023-03-15 13:35:03",
                "update_datetime": "2023-03-15 14:22:22",
                "children": [
                    {
                        "id": 22,
                        "children": [
                            {
                                "id": 27,
                                "children": [],
                                "description": null,
                                "modifier": "2",
                                "dept_belong_id": "1",
                                "update_datetime": "2023-03-22 14:03:35",
                                "create_datetime": "2023-03-22 14:03:35",
                                "is_deleted": false,
                                "name": "BBB",
                                "is_root": false,
                                "index": 0,
                                "function_field": null,
                                "function_text": null,
                                "is_show": true
                            }
                        ],
                        "description": null,
                        "modifier": "2",
                        "dept_belong_id": "1",
                        "update_datetime": "2023-03-17 23:35:21",
                        "create_datetime": "2023-03-17 23:35:21",
                        "is_deleted": false,
                        "name": "测试设备A",
                        "is_root": false,
                        "index": 0,
                        "function_field": null,
                        "function_text": null,
                        "is_show": true
                    }
                ],
                "has_children": 1,
                "description": null,
                "modifier": "2",
                "dept_belong_id": "1",
                "is_deleted": false,
                "name": "201",
                "is_root": false,
                "index": 0,
                "function_field": null,
                "function_text": null,
                "is_show": true
            },
            {
                "id": 17,
                "modifier_name": "超级管理员",
                "creator_name": "超级管理员",
                "create_datetime": "2023-03-15 13:38:13",
                "update_datetime": "2023-03-15 13:38:13",
                "children": [],
                "has_children": 0,
                "description": null,
                "modifier": "2",
                "dept_belong_id": "1",
                "is_deleted": false,
                "name": "12345",
                "is_root": false,
                "index": 0,
                "function_field": null,
                "function_text": null,
                "is_show": true
            },
            {
                "id": 25,
                "modifier_name": "超级管理员",
                "creator_name": "超级管理员",
                "create_datetime": "2023-03-22 10:50:45",
                "update_datetime": "2023-03-22 10:50:45",
                "children": [
                    {
                        "id": 26,
                        "children": [],
                        "description": null,
                        "modifier": "2",
                        "dept_belong_id": "1",
                        "update_datetime": "2023-03-22 10:50:57",
                        "create_datetime": "2023-03-22 10:50:57",
                        "is_deleted": false,
                        "name": "123",
                        "is_root": false,
                        "index": 0,
                        "function_field": null,
                        "function_text": null,
                        "is_show": true
                    }
                ],
                "has_children": 1,
                "description": null,
                "modifier": "2",
                "dept_belong_id": "1",
                "is_deleted": false,
                "name": "1223",
                "is_root": false,
                "index": 0,
                "function_field": null,
                "function_text": null,
                "is_show": true
            }
        ]
    },
    "msg": "获取成功"
}

要彻底解决这个问题,可以重写view的destroy方法:

代码语言:javascript
复制
def destroy(self, request, *args, **kwargs):
    '''重写删除代码 删除之后父分类设置为空'''
    instance = self.get_object()
    DeviceGroup.objects.filter(parent=instance).update(parent=None)
    instance.delete()
    return DetailResponse(data=[], msg="删除成功")
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023年3月23日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档