2012-11-12 3 views
5

で基本クラスをフィルター:Djangoは、私はジャンゴで、以下のモデルの継承構造を持っている子クラス名

class Parent(models.Model): 
    # stuff 

class A(Parent): 
    # stuff 

class B(Parent): 
    # stuff 

class C(Parent): 
    # stuff 

and the list goes on. 

私のようなオブジェクトフィルタリングするジャンゴモデル-utilsののInheritanceManagerを使用しています:

Parent.objects.filter(foo=bar).select_subclasses() 

をこれは、すべてのサブクラスをフィルタリングするときにうまく機能します。私がしたいのは、AオブジェクトとBオブジェクトをフィルタリングすることですが、Cオブジェクトはフィルタリングしません。私は、このようなフィルタリング操作を行うことが可能になり、どのように可能な場合は

Parent.objects.filter(foo=bar, __class__.__name__=A, __class__.__name__=B).select_subclasses() 

のような単一のクエリでこれを行うにはしたいですか?

+0

「A.objects.filter(foo = bar) –

+0

複数のクエリではなく、1つのクエリですべてのオブジェクトをフィルタリングしたい –

答えて

0

通常、各SQLクエリが結合を行う必要があるため、そのような継承可能な設定には最も適しているとは考えられません。それはあなたのパフォーマンスをはるかに遅くすることができます。パフォーマンスを向上させるために、あなたはabstractメタ値使用することができます。この方法で

class Parent(models.Model): 
    # stuff 
    class Meta: 
     abstract = True 

を各テーブルには、独立しており、したがって、パフォーマンスが速くなります。

これは当てはまりませんが、テーブル/モデル内のフィールドにはどのテーブルの情報が含まれていないため、そのようなことは一度もないと思われます。その場合、どういうわけかInheritanceManagerをサブクラス化する必要がありますが、私はそこで何をすべきか分かりません。あなたがそうした場合は、content_typesを使用すると助けになるかもしれません。

これはあまりにも多くの作業がある場合は、いつでも簡単なハック(猿のパッチの詳細...)を行うことができます。私はそのきれいではありませんを知っているが、それは動作します:データベースへのより多くの情報を追加することなく、私のために働いています

class Parent(models.Model): 
    # stuff 
    table = models.CharField(max_length=8, default='parent') 

class A(Parent): 
    # stuff 
    table = models.CharField(max_length=8, default='a') 

class B(Parent): 
    # stuff 
    table = models.CharField(max_length=8, default='b') 


# and then something like 
# please note that I've never used django-model-utils 
# so don't know the correct syntax 
Parent.objects.filter(foo=bar, table__in=['parent', 'a']).select_subclasses() 
+0

ありがとうございました。私は抽象基本クラスを使用しませんでした。なぜなら、各サブクラスに対して別々のクエリを使用するのではなく、単一のクエリを使用して基本クラスオブジェクトをフィルタリングする機能が必要だったからです。私はちょうどいくつかの場所でベースクラスのサブセットをフィルタリングし、別のサブセットを別の場所にフィルタリングしたいと考えました。私は満足のいく解決策を見つけたらここに投稿します –

0

別のハック解決策:

letters = Parent.objects.filter(foo=bar) 
for letter in letters: 
    if type(letter) == C: 
     letters.exclude(id=c.id) 

あるいは、あなたがに情報を追加した場合フィールドを追加することなく、モデル:

class Parent(models.Model): 
    # stuff 

class A(Parent): 
    code = 'A' 
    # stuff 

class B(Parent): 
    code = 'B' 
    # stuff 

class C(Parent): 
    code = 'C' 
    # stuff 

そして...

letters = Parent.objects.filter(foo=bar) 
for letter in letters: 
    if letter.child().code == 'C': 
     letters.exclude(id=c.id) 

私の目的のために動作しますが、まだハックです...

関連する問題