2

私は部品データベースに取り組んでいます。ここでは、すべての部品番号をアセンブリにすることもできます。つまり、任意の数の他の部品で構成されています (さらにループを続けることができ、サブ部品はさらに多くの部品で構成されています)。そのため、2 つのデータベース テーブルがあり、1 つは部品情報用で、もう 1 つは関係情報 (「サブ部品」番号にリンクされた部品番号) 用です。「アセンブリ」、「パーツ」、および「サブパーツ」はすべて、最終的には単なる「パーツ」であることに注意してください (ちょっと混乱しますが、より DRY で汎用性の高いデータベースが可能になります)。

現在、select_related 呼び出しを使用して、モデルで使用されている ForeignKeys を追跡しています。ただし、私のクエリは 1 つ以上の結果を返す可能性があるため (複数のサブパーツの場合)、"get" ルックアップを使用できず、代わりに "filter" を使用しています。そのため、すべて get クエリに基づいているドキュメントに示されている例に従うことはできません。

select_related クエリは、意図したものを取得しているようです (DjangoDebugToolbar によって表示される生の SQL クエリに基づいて)。でも、呼び方がわからない!関連するテーブルの値を表示するための正しい構文または方法は何ですか? 返されたクエリセット内のすべてのインスタンスをループするにはどうすればよいですか? 以下のテンプレートのスニペットは、結果として取得しようとしているものを最も効果的に示しているはずです。ありがとう。

#----------------
#MODEL SNIPPET
#----------------
class Part(models.Model):
    ISC_CHOICES = ( #intentionaly removed for this question 
    )
    part_no = models.CharField(max_length=15, primary_key=True)
    description = models.CharField(max_length=40, blank=True, null=True)
    isc = models.CharField(max_length=2, choices=ISC_CHOICES)
    rev = models.CharField(max_length=2, blank=True, null=True)

#this table relates subparts to the part model above- basically is a manual many-to-many field
class PartAssembly(models.Model):
    id = models.AutoField(primary_key=True)
    part_no = models.ForeignKey(Part, related_name="partno_set")
    subpart = models.ForeignKey(Part, related_name="subpart_set")
    qty = models.IntegerField(max_length=3)
    item_no = models.IntegerField(max_length=3)


#----------------
#VIEW SNIPPET
#----------------
def assembly_details(request, assembly_no): #assembly_no passed through URL
    context_instance=RequestContext(request)
    subpart_list = PartAssembly.objects.filter(part_no=assembly_no).select_related()
    return render_to_response('assembly_details.html', locals(), context_instance,)


#-------------------
# TEMPLATE SNIPPET
#-------------------
{% for partassembly in subpart_list %} 
# obviously, this  loop doesnt return anything for my part.foo variables below
# it does work for the partassembly.bar
        <tr>
            <td>{{ partassembly.item_no }}</td> #EDIT: comments are correct
            <td>{{ partassembly.subpart }}</td> #partassembly.subpart.part_no
            <td>{{ part.description }}</td> #partassembly.subpart.description
            <td>{{ part.rev }}</td>     #partassembly.subpart.rev   
            <td>{{ partassembly.qty }}</td>
            <td>{{ part.isc }}</td>         #partassembly.subpart.isc
        </tr>

助けてくれてありがとう

4

2 に答える 2

4

あなたの問題がどこにあるのか正確にはわかりません。select_related()関連するインスタンスのオブジェクト アクセスは決して変更されないことに注意してください。partassembly.part_no.revしたがって、を使用していないかのように、などを参照しますselect_related

于 2011-03-07T22:58:07.003 に答える
2

すべては、モデル内でselect_related宣言されたフィールドを積極的にフェッチすることです。ForeignKey余分なデータベース呼び出しを回避しようとしますが、余分なフィールドへのアクセスを魔法のように与えるわけではありません。

あなたの例では、呼び出しで熱心にフェッチされたため、アクセスpartassembly.subpartしても余分なデータベースが選択されないことを意味しPartAssembly.objects.filter()ます。

あなたのデータ モデルは間違っているようですが、それについてはすぐに説明します。最初に、現在のデータ モデルを使用してすべての断片にアクセスする方法を示します。

{% for partassembly in subpart_list %} 
        <tr>
            <td>{{ partassembly.item_no }}</td>
            {% for subpart in partassembly.subpart.subpart_set %} # database hit
                 <td>{{ subpart.subpart }}</td>
                 <td>{{ subpart.subpart.description }}</td> # database hit
                 <td>{{ subpart.subpart.rev }}</td>         
                 <td>{{ subpart.qty }}</td>
                 <td>{{ subpart.subpart.isc }}</td>
            {% endfor %}
        </tr>

残念ながら、どこまで再帰する必要があるかを知る方法はありません。元の PartAssembly 内のパーツにアクセスでき、その Part から PartAssembly のセットに到達できますが、最初の PartAssembly 内のすべてのパーツの PartAssembly セットに到達する簡単な方法はありません。うわー、それは一口でした!

次に、データ モデルについて説明します。

「3mm ネジ」と呼ばれる部品があるとします。それは多くの異なるアセンブリに使用できるように思えます (私は意図的に「ies」の複数形を使用していません)。つまり、デスクと呼ばれるアセンブリと、チェアと呼ばれるアセンブリがあります。それぞれがこれらの3mmネジを多く使用しています。デスクの作り方を説明したい。

 desk = PartAssembly.objects.filter(id=assemblyid)
 part = desk.subpart # lets pretend this returns a 3mm screw
 subassemblies = part.subpart_set.all()
 for a in subassemblies:
     a.subpart.description # could be a Chair, or a Desk, or anything really!

これは、3 mm ねじ (または任意のパーツ) の 1 つのインスタンスがすべてのアセンブリ間で共有されているために発生します。ManyToMany テーブルを真にレプリケートしているわけではありません。あなたのデータモデルは、単一のパーツを多くのアセンブリで使用できると言っています。

あなたが本当に言いたいのは、アセンブリが別のアセンブリの一部になることができるということです。各アセンブリは、その構成に関連付けられた多数のパーツとして表示されます。

class Assembly(models.Model):
    parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
    parts = models.ManyToManyField(Part)
    name = models.CharField(max_length=..)

さて、椅子を作りたいときは、次のようにすることができます:

assembly = Assembly.objects.get(name='Chair')
children = assembly.children.all()
print assembly
for part in assembly.parts:
    print part
# now you iterate over the tree of children, printing their parts as you go

そのため、アセンブリ モデルは、それぞれ独自のパーツ セットを含む他のアセンブリのツリー構造に変換されました。これがツリー構造であることを認識できたので、Django 内のデータベースでこの構造を表現する方法を調べることができます。

幸いなことに、まさにこれを行うライブラリが存在します。django-mpttは、ツリー構造を表現するのに役立ちます。ツリー全体を反復し、テンプレートで各ツリーを記述するためのメソッドを提供します。

私はおそらくあなたが必要だと思っていたよりも多くの仕事をさせてしまったことを知っていますが、これは本当にあなたを助けると思います.

幸運を祈ります。

于 2011-03-07T23:16:41.847 に答える