为分层模型(django)创建有效的数据库查询

| 考虑以下(Django)模型:
class Source(models.Model):
   # Some other fields
   type = models.ForeignKey(\'Type\')

class Type(models.Model):
    # Some other fields
    parent = models.ForeignKey(\'self\')
该模型本身具有外键,因此可以创建层次结构。 假设我们具有以下层次结构:
Website
    Blog
    News    
    Social Network
    Q&A
    Forum
Radio
    Government radio
    Pirate radio
    Commercial radio
    Internet radio
我如何有效地查询,以便如果我选择
Type
来选择
Source
,我还检索具有ѭ3child且是给定类型的子项的
Sources
? 我已经尝试遍历整个树,但是显然效率不是很高。 另一种选择是使用ManyToManyField并通过覆盖save()方法自动附加父类型。例如,如果选择“博客”,则还将创建“网站”的记录。但这对我来说似乎太过分了。     
已邀请:
django-mptt或django-treebeard是分层数据的强大帮助者。它们都向模型添加了额外的元数据,以允许高效的查询。 如果选择使用django-treebeard,则模型可能如下所示:
from django.db import models
from treebeard.mp_tree import MP_Node

class Source(models.Model):
    # Some other fields
    type = models.ForeignKey(\'Type\')

class Type(MP_Node):
    # Some other fields
    name = models.CharField(max_length=100)

    # parent gets added automatically by treebeard
    # parent = models.ForeignKey(\'self\', blank=True, null=True)
可以这样查询:
# get all Sources of Type type and descendants of type
type = Type.objects.get(name=\'Radio\')
Source.objects.filter(type__in=type.get_descendants())
请参阅https://tabo.pe/projects/django-treebeard/docs/tip/api.html了解更多可能的查询     
使用递归公用表表达式可以很容易地检索到这种结构。 一个例子是此处:http://www.postgresql.org/docs/current/static/queries-with.html     
  我如何有效地查询,以便   我按类型选择来源,我也   检索具有类型的源   那是给定类型的孩子? 对于给定的示例,因为不需要进行递归调用,并且您的“层次结构”仅深一层,因此设置查询非常容易:
class Source(models.Model):
   # Some other fields
   type = models.ForeignKey(\'Type\')

class Type(models.Model):
    # Some other fields
    name = models.CharField(max_length=100)
    parent = models.ForeignKey(\'self\', blank=True, null=True)

#We want all sources under in the type = Radio tree
type = Type.objects.get(name=\'Radio\')
qs = Source.objects.filter(type__parent=type)

#We want all sources that are `Forum` typed
type = Type.objects.get(name=\'Forum\')
qs = Source.objects.filter(type=type)
假设Source始终与\“ child \”类型相关,而不与\“ parent” \相关。 如果源也可以与\“ parent \”类型相关,则可以对复杂查询使用Q:
>>> from django.db.models import Q
>>> type = Type.objects.get(name=\'Radio\')
>>> qs = Source.objects.filter(Q(type=type)|Q(type_parent=type))
>>> #if Radio type id = 2
>>> print qs.query
SELECT `app_source`.`id`, `app_source`.`type_id` FROM `app_source` INNER JOIN `app_type` ON  (`app_source`.`type_id` = `app_type`.`id`) WHERE (`app_source`.`type_id` = 2  OR `app_type`.`parent_id` = 2 )
>>> 
如果您的表中有一个真正的分层树,则此方法的可用性将大大降低,因此您应该寻求另一种解决方案。     

要回复问题请先登录注册