亲子关系效率

时间:2012-03-14 16:02:36

标签: python django parent-child

我在我的一个Django应用程序中有一个图像字段,但希望能够存储图像的修订版,以便允许我按修订顺序显示列表。这是最好的方法来分别存储图像,然后与父母图像有一个“父”的ForeignKey关系?例如:

class Image(models.Model):
    name = models.CharField(max_length=50)
    parent = models.ForeignKey(Image, null=True)
    image = models.ImageField(upload_to='images')

如果没有父(null=True),则图像必须没有修订。每个对象只能有一个父对象和一个子对象,但层数可能是无限的。

我不知道是否可以遍历多层子节点而不会产生大量的SQL查询,这会使应用程序效率非常低。根据Django对象表示这个的最佳方法是什么?例如,有一个单独的“ImageRevision”对象处理图层是否更好?

由于

2 个答案:

答案 0 :(得分:1)

我看到有效的两种方法:

  1. Image绑定到它所使用的模型上,允许图像的一对多:

    class Image(models.Model):
        obj = models.ForeignKey(MyModel, related_name='images')
        name = models.CharField(max_length=50)
        image = models.ImageField(upload_to='images')
        created = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            ordering = ['-created']
            get_latest_by = 'created'
    

    然后你可以通过以下方式获得最新版本:

    my_model_instance.images.latest()
    
  2. 如您所述创建ImageRevision模型并将其绑定到Image

    class Image(models.Model):
        name = models.CharField(max_length=50)
    
    class ImageRevision(models.Model):
        parent = models.ForeignKey(Image, related_name='revisions')
        image = models.ImageField(upload_to='images')
        created = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            ordering = ['-created']
            get_latest_by = 'created'
    

    然后,您可以通过以下方式获取最新版本:

    my_model_instance.image.revisions.latest()
    
  3. 第二种方法涉及额外关系的附加查询(尽管您应该能够通过明智地使用select_related来减轻这种关系),但是具有能够与多个不同模型一起使用的好处,而第一种方法将Image本质上绑定到一个模型。

答案 1 :(得分:0)

在这种情况下我可能会做的是使用单独的修订对象。从Image中删除父字段(除此之外,它将是OneToOne而不是ForeignKey,以防止来自单个父项的多个子项)。所以,你有一个带有名字的Image对象和一个带有ImageField的修订对象,如下所示:

class Image(models.Model):
    name = models.CharField(max_length=50)
    def __unicode__(self):
        return self.name

class Revision(models.Model):
    image = models.ForeignKey(Image)
    revision_number = models.IntegerField()
    file = models.ImageField(upload_to='images')

遍历,然后不需要通过链递归。像这样:

for i in Image.objects.all():
    print i.name
    for r in Revision.objects.filter(image=i).order_by('revision_number'):
        print "rev. " + str(r.revision_number) + " " str(r.file)

至少我会如何处理它。

干杯