2

私は次のようなDjangoモデルを持っています:

class Category(models.Model):
    status=models.CharField(max_length=16)
    machineName=models.CharField(max_length=50)
    readableName=models.CharField(max_length=100)
    description=models.CharField(max_length=1024)
    parents=models.ManyToManyField('self')

各カテゴリが多くの親に存在する可能性がある場合。一部のカテゴリには親がなく、「ルート」カテゴリです。プレーンSQLでは、次の方法でそれらを見つけることができます。

SELECT "readableName"
FROM foo_category AS c
LEFT JOIN foo_category_parents AS cp ON (c.id=cp.from_category_id)
WHERE cp.to_category_id IS NULL;

そして確かに、これはうまく機能します。Django-yの呼び出しで「親のないカテゴリのリスト」を見つけるにはどうすればよいですか?私は試した:

# Says "Cannot resolve keyword 'is_null' into field."
Category.objects.filter(parents__is_null=True)
# Says "Join on field 'id' not permitted."
Category.objects.filter(parents__pk_null=True)

しかし、前述のように、どちらも機能しません。

4

1 に答える 1

7

Djangoの多対多フィールドは通常、対称的に動作します(Djangoドキュメントのこのエントリを参照してください)。自分自身に対してManyToManyを実行すると、これは逆のManyToManyエントリが作成されることを意味します。したがって、実際には、親を持つすべてのカテゴリが親の親になります(それが理にかなっている場合)。

言い換えると:

a = Category.objects.create(name='a')
b = Category.objects.create(name='b')
b.parents.add(a)

print b.parents.all() # produces [a]
print a.parents.all() # produces [b], which is why your filter is failing

これを回避するために、特別なオプションがあります。

class Category(models.Model):
    # ... as above ...
    parents=models.ManyToManyField('self', symmetrical=False)

これで、次の親カテゴリを取得できます。

 Category.objects.filter(parents=None)
于 2009-05-20T17:51:44.103 に答える