我正在尝试遍历给定 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 方法。
碰巧,这个基类适用于所有 13 个可以使用 ClusteringWIP 作为外键的模型,所以简单地遍历所有相关的(不管类)会完成同样的事情,所以如果这恰好是最好的方法,一定要让我知道。但我仍然很想知道上述问题的答案,无论将来如何使用。
另外,在寻找这个答案的旅途中,我偶然发现了一个 django pre_delete信号似乎更符合我在这里尝试做的事情(即在删除 ClusteringWIP 时取消任何相关模型的“cluster_comment”字段)如果有人可以向我展示一个示例,说明如何使用它来完成非常感谢我的任务。
谢谢。
最佳答案
您可以使用 ClusteringRecord 的子类() 方法。例如:
@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()
关于python - 遍历抽象 Django 模型的所有外键相关子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25670176/