【问题标题】:Updating a model when an object it references through a ManyToMany relation is deleted当通过多对多关系引用的对象被删除时更新模型
【发布时间】:2021-09-01 05:04:20
【问题描述】:

例如,我有一个模型

class ModelA(models.Model):
  name = models.CharField()

class ModelB(models.Model):
  last_modified_time = models.DateTimeField()
  as = models.ManyToManyField('ModelA')

当我删除 ModelA 的实例时,我还想更新所有引用 ModelA 的 ModelB 实例上的 last_modified_time 字段。我可以为此使用预删除信号,即

def pre_delete_handler(sender=None, instance=None, *args, **kwargs):
   # update all using instance.modelbs...

models.signals.pre_delete.connect(pre_delete_handler, sender=ModelA)

但是每次新模型通过 ManyToMany 引用它时,这段代码都需要更新,从维护的角度来看,这并不是最好的。我正在寻找一种方法来枚举 ModelA 引用的所有模型,这样我就可以进行一个涵盖所有情况的更新,但无法找出最好的方法。枚举与 ModelA 相关的所有对象的正确方法是什么?

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    如果所有引用A 为多对多的模型都有字段last_modified_time,那么这样的事情可以工作:

    from django.db.models.fields.reverse_related import ManyToManyRel
    from django.utils import timezone
    
    
    def pre_delete_handler(sender=None, instance=None, *args, **kwargs):
        if not instance:
            return
    
        # Get all reverse m2m fields
        reverse_m2m_fields = [m for m in instance._meta.model._meta.get_fields() if isinstance(m, ManyToManyRel)]
        # or [m for m in ModelA._meta.get_fields() if isinstance(m, ManyToManyRel)]
    
        for f in reverse_m2m_fields:
            # Find the name of the reverse m2m field from this model
            field_name = f.related_name or f.related_query_name or f'{f.name}_set'
            getattr(instance, field_name).update(last_modified_time=timezone.now())
    
    
    models.signals.pre_delete.connect(pre_delete_handler, sender=ModelA)
    

    【讨论】:

    • 太棒了,工作得很好,非常感谢布赖恩。唯一的补充是从相关对象中删除实例以避免留下一个孤立的对象remote_field_name = f.remote_field.name'getattr(object, remote_field_name).remove(instance)
    • 不客气!关于那个删除实例,我知道我认为这将由删除本身完成。
    猜你喜欢
    • 2015-06-17
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    • 2012-03-23
    • 2015-03-03
    • 1970-01-01
    • 2012-05-25
    • 1970-01-01
    相关资源
    最近更新 更多