簡體   English   中英

迭代抽象django模型中所有與外鍵相關的子項

[英]Iterating through all foreign key related children of an abstract django model

我試圖迭代給定django模型的所有外鍵相關模型。 可能有13種不同的模型可能具有外鍵關系,但它們都繼承了相同的抽象基類。 我想在一個循環中遍歷所有這些,以修改屬於父類的字段。 我的代碼看起來像。

class ClusteringRecord(models.Model):
    """
    An abstract class to hold data that is repeated from model to model
    """

    wip = models.ForeignKey(
        ClusteringWIP, null=True, on_delete = models.SET_NULL)
    cluster_comment = models.CharField(max_length=1000, null=True, blank=True)

    class Meta:
        abstract = True


class ClusteringNPIRecord(ClusteringRecord):
    """Django Model object representing an NPI record that was not able to be
    clustered by automatic clustering logic in the database.
    """

    npi_id = models.CharField(max_length=1000, null=True)
    npi_number = models.CharField(max_length=1000, null=True)


class ClusteringDEARecord(ClusteringRecord):
    """Django Model object representing a DEA record that was not able to be
    clustered by automatic clustering logic in the database.
    """

    dea_id = models.CharField(max_length=1000, null=True)
    dea_number = models.CharField(max_length=1000, null=True)

我想要使​​用的代碼如下所示:

def cancel_and_return(request, list_type, wip_id):
    """
    destroys lock object and returns user to most recent version of worklist
    :param request:
    :param wip_id: pk of current ClusteringWIP
    :return: HTTP redirect to worklist home
    """
    wip = ClusteringWIP.objects.select_related().get(pk=wip_id)
    for record in wip.clusteringrecord_set.all():
        record.cluster_comment = None
        record.save()
    wip.delete()

但它告訴我clusteringrecord_set無效。 有沒有辦法迭代這個與提供者相關的類的所有子節點? 否則我使用13個不同的for循環來實現這一點並公然違反DRY方法。

實際上,這個基類適用於可能使用ClusteringWIP作為外鍵的所有13個模型,因此簡單地遍歷所有相關(無論類)將完成相同的事情,所以如果這恰好是最好的方法這樣做,請務必告訴我。 但我仍然很想知道上述問題的答案,無論將來的用法如何。

此外,在我尋找這個答案的旅行中,我偶然發現了一個django pre_delete信號, 這個信號似乎更符合我在這里嘗試做的事情(即刪除了ClusteringWIP時,任何相關模型的'cluster_comment'字段無效如果有人能告訴我一個如何用它來完成我的任務的例子,我將非常感激。

謝謝。

您可以使用ClusteringRecord的subclass ()方法。 例如:

@classmethod
def related_set(cls, wip):
  classes = cls.__subclasses__()
  return sum([c.objects.filter(wip=wip).all() for c in classes], [])

並使用它來迭代你的對象。

對於pre_delete信號,您需要在應用程序中有一個signals.py文件,它看起來像這樣:

from django.db.models.signals import pre_delete, post_delete
from django.dispatch import receiver

from myapp.models import ClusteringWIP

@receiver(pre_delete, sender=ClusteringWIP)
def on_instance_delete(sender, instance, **kwargs):
    instance.on_pre_delete()

使用ClusteringWIP :: on_pre_delete方法如下:

def on_pre_delete(self):
  for record in ClusteringRecord.related_set(self):
    record.cluster_comment = None
    record.save()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM