Django 继承模型中的 ForeignKey _set

7 投票
3 回答
8126 浏览
提问于 2025-04-16 10:58

我有两个模型,分别是 Category(分类)和 Entry(条目)。还有一个模型 ExtEntry(扩展条目),它是从 Entry 继承过来的。

class Category(models.Model):
    title = models.CharField('title', max_length=255)
    description = models.TextField('description', blank=True)
    ...

class Entry(models.Model):
    title = models.CharField('title', max_length=255)    
    categories = models.ManyToManyField(Category)
    ...

class ExtEntry(Entry):    
    groups= models.CharField('title', max_length=255)
    value= models.CharField('title', max_length=255)
    ...

我可以使用 Category.entry_set 来获取条目,但我想用 Category.blogentry_set 来获取扩展条目,但这个方法不可用。如果这个方法不可用,那我需要找其他办法来获取与特定 Category 相关的所有 ExtEntry

编辑:我的最终目标是得到一组 ExtEntry 对象。

谢谢!

3 个回答

0

你遇到的问题是因为 EntryExtEntry 在不同的表里。这种做法可能对你来说是最好的选择,但在你决定使用多表继承的时候,得注意这一点。

category.entry_set.exclude(extentry=None) 这样的写法应该能解决你的问题。

2

你可以在这里查看文档,了解这个是怎么运作的:这里

简单来说,因为你可以获取父模型的项目,所以你应该也能获取到它的子模型,因为它们之间有一种隐含的一对一关系。

这种继承关系在子模型和每个父模型之间建立了链接(通过一个自动创建的OneToOneField)。

所以,你应该可以这样做:

categories = Category.objects.all()
for c in categories:
    entries = c.entry_set.all()
    for e in entries:
        extentry = e.extentry
        print extentry.value

虽然我没有看到相关的文档,但我相信一般来说,你的一对一字段名称会是继承模型名称的小写版本。

4

我需要另一种方法来获取与某个特定类别相关的所有 ExtEntry。

简单:

ExtEntry.objects.filter(categories=my_category)

你知道有没有办法使用继承的 _set 特性吗?

我不知道有没有直接的方法。文档里没有提到。

不过,可以用 select_related 来获得类似的结果。

for e in category.entry_set.select_related('extentry'):
    e.extentry # already loaded because of `select_related`, 
               # however might be None if there is no Extentry for current e

可以选择只包含 ExtEntry 的条目:

for e in category.entry_set.select_related('extentry').exlude(extentry=None):
    e.extentry # now this definitely is something, not None

排除的坏处是,它会生成非常低效的查询:

SELECT entry.*, extentry.* FROM entry
LEFT OUTER JOIN `extentry` ON (entry.id = extentry.entry_ptr_id) 
WHERE NOT (entry.id IN (SELECT U0.id FROM entry U0 LEFT OUTER JOIN 
                        extentry U1 ON (U0.id = U1.entry_ptr_id) 
                        WHERE U1.entry_ptr_id IS NULL))

所以我的总结是:使用 ExtEntry.objects.filter() 来获取你的结果。反向关系(object.something_set)只是一个方便的功能,并不是在所有情况下都能用。

撰写回答