在Django 3 / Python中,删除孤立记录的首选方法是什么?

问题描述

我正在使用Django 3和Python 3.8。我有以下模型...

class Coop(models.Model):
    objects = CoopManager()
    name = models.CharField(max_length=250,null=False)
    types = models.ManyToManyField(CoopType,blank=False)
    addresses = models.ManyToManyField(Address)
    enabled = models.BooleanField(default=True,null=False)
    phone = models.ForeignKey(ContactMethod,on_delete=models.CASCADE,null=True,related_name='contact_phone')
    email = models.ForeignKey(ContactMethod,related_name='contact_email')
    web_site = models.TextField()

请注意“电话”和“电子邮件”外键列。是否有任何Django / Python特定的方法可以将ContactMethod记录变为孤立后自动删除它们?也就是说,如果我有我的模型,则在其中填充两列,然后运行

coop.phone = None
coop.save(update_fields=['phone'])

有什么东西可以自动删除孤立记录吗?还是我想实现这一目标的标准方法是什么?我正在运行MySql 8数据库,但我希望排除特定于数据库的解决方案。

解决方法

您可以定义Django信号,但是Django信号并不总是运行。特别是当您进行执行批量更新或批量删除的ORM调用时。例如,如果您将所有email中的phone和/或Coop设置为enabled=FalseCoop.objects.filter(enabled=False).update(email=None,phone=None),则它将不会运行post_save信号,因此某些ContactMethod可以孤立而无需触发信号。

即使您可以使用信号,也可能不是一个好主意。还可以在没有ORM查询的情况下对数据库进行更新,例如通过 PhpMyAdmin 前端的数据库管理员。因此,即使在Django中可行,这也意味着人们仍然可以通过另一种方式孤立对象。此外,这样的信号一次只能处理一个ContactMethod,这比删除 bulk 中的ContactMethod要昂贵。

您可以设置management command [Django-doc],使其可以定期运行,例如每天运行一次。您可以在 app 中定义这样的管理命令:

app/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            remove_orphan_contactmethod.py
    urls.py
    views.py

然后在app/management/commands/remove_orphan_contactmethod.py中,您可以检测并删除以下ContactMethod对象:

from django.core.management.base import BaseCommand,CommandError
from app.models import ContactMethod

class Command(BaseCommand):
    help = 'Remove ContactMethods not referenced through email or phone'

    def handle(self,*args,**options):
        items = ContactMethod.objects.filter(
            contact_phone=None,contact_email=None
        ).delete()
        number = items.get('app.ContactMethod',0)
        self.stdout.write(self.style.SUCCESS(f'Removed {number} ContactMethod object(s)'))

然后您可以运行:

python3 manage.py remove_orphan_contactmethods

运行命令。例如,您可以指定cronjob [wiki]或其他一些重复执行的任务机制,以一定频率执行此命令。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...