1

次のモデルを想定しています。

class Category(models.Model):
    related = models.ManyToManyField('self', symmetrical = False, through = 'CategoryRelation', null = True, blank = True)

次の中間の「から」の関係を想定します。

class CategoryRelation(models.Model):
    source = models.ForeignKey('Category', null = False, blank = False, verbose_name = _('source'), related_name = 'relation_source')

    target = models.ForeignKey('Category', null = False, blank = False, verbose_name = _('target'), related_name = 'relation_target')

    order = models.PositiveIntegerField(_('order'), null = False, blank = True, default = 0)

    class Meta:
        ordering = ( 'order', )

順序を維持しながら、特定のカテゴリに関連するカテゴリオブジェクトを取得するにはどうすればよいですか?次のコードは、正しい順序ではなく正しいカテゴリオブジェクトを生成し、次を使用している場合でもクエリセットに重複するエントリを含めます.distinct()

relations = CategoryRelation.objects.filter(source = self)

Category.objects.filter(relation_target__in = relations).order_by('related')
4

1 に答える 1

5

以下は正しく順序付けするために機能しますが、重複するエントリを除外しません:

relations = CategoryRelation.objects.filter(source = self)

Category.objects.filter(relation_target__in = relations).order_by('relation_target')

.order_by() ロジックは後で適用されるため、.distinct() を呼び出しても違いはありません。ただし、この場合、順序が正の整数フィールドであるという事実を利用し、各カテゴリに relationship_target フィールドの順序フィールドの最小値で注釈を付け、この新しい注釈フィールドを順序付けに使用することができます。

return Category.objects.filter(relation_target__in = relations).annotate(relation_target_order = models.Min('relation_target__order')).order_by('relation_target_order')

これでほぼ完了ですが、このクエリのセマンティクスは本質的に一意であるため、後で他の個別のクエリと組み合わせて実行できるように、distinct() を呼び出して、distinct フラグが True であることを確認することをお勧めします。

return Category.objects.filter(relation_target__in = relations).annotate(relation_target_order = models.Min('relation_target__order')).order_by('relation_target_order').distinct()

この場合、.distinct() はクエリにまったく影響を与えませんが、db/models/sql/query.py メソッドの結合 (自己、rhs、コネクタ) がそのアサーションを確実に渡すようにします。

assert self.distinct == rhs.distinct, \ ...
于 2009-08-12T12:24:17.997 に答える