2

mainDjango 1.3という名前のアプリで、次のデータを使用してこれらのモデルを初期化しました。

from django.db.models import Model, FloatField, CharField, ForeignKey, Q

class Customer(Model):
    name = CharField(max_length=64)

class Order(Model):
    customer = ForeignKey(Customer)
    order_total = FloatField()
c = Customer(name="John Smith")
c.save()

Order(customer=c, order_id=9).save()
Order(customer=c, order_id=13).save()

Q()オブジェクトを使用して、注文 9 と注文 13 を所有する顧客を検索するクエリを作成するにはどうすればよいですか?

Q()オブジェクトを使用しなくても、.filter()メソッドを 2 回使用して目的の結果を得ることができます。ご覧のとおり、2 つJOINの s を使用して 2 つの外部キーを検索します。

queryset = Customer.objects.filter(order__order_id=9).filter(order__order_id=13)

return HttpResponse("%s\n\n%s" % (queryset, queryset.query), content_type="text/plain")
[<Customer: Customer object>]

SELECT "main_customer"."id", "main_customer"."name"
FROM "main_customer"
INNER JOIN "main_order" ON ("main_customer"."id" = "main_order"."customer_id")
INNER JOIN "main_order" T3 ON ("main_customer"."id" = T3."customer_id")
WHERE ("main_order"."order_id" = 9  AND T3."order_id" = 13 )

Q()次のようにオブジェクトを使用して同じことを試みました。ID 9 と ID 13 の 2 つの異なる注文を参照していることを理解する代わりに、ID 9 と 13 の両方を持つ単一の注文を探していると考えます。これは明らかに不可能であるため、結果は返されません。 :

q = Q(order__order_id=9) & Q(order__order_id=13)
queryset = Customer.objects.filter(q)

return HttpResponse("%s\n\n%s" % (queryset, queryset.query), content_type="text/plain")
[]

SELECT "main_customer"."id", "main_customer"."name"
FROM "main_customer"
INNER JOIN "main_order" ON ("main_customer"."id" = "main_order"."customer_id")
WHERE ("main_order"."order_id" = 9  AND "main_order"."order_id" = 13 )

Django のエンジンが両方のクエリを同等に解釈することを期待していましたが、どうやらQ()オブジェクトの処理が異なっているようです。複数回Q()呼び出すのではなく、オブジェクトを使用して複数の外部キー参照でオブジェクトをフィルタリングするにはどうすればよいですか?.filter()

4

2 に答える 2

1

これについての説明は、Djangoのドキュメントにあります。私が観察した動作は、予想される動作です。複数値の関係のクエリ用語は、.filter()/への同じ呼び出し内で適用された.exclude()場合と、異なる呼び出し内で適用された場合とでは、異なる方法で処理されます。

.filter()同じ呼び出し内で2つのクエリ用語を適用すると...

queryset = Customer.objects.filter(Q(order__order_id=9) & Q(order__order_id=13))
# or equivalently: .objects.filter(Q(order__order_id=9), Q(order__order_id=13))

...次に、Customer両方の制約を満たす注文を所有するsのみを返しますorder_id=9 AND order_id=13。用語はOrderいつでも同じものを参照する必要があります。

一方、2つの異なる.filter()呼び出しを使用してクエリ用語を適用すると...

queryset = Customer.objects.filter(order__order_id=9).filter(order__order_id=13)

...同じものを参照する必要はありませんOrder。これは、2段階の操作と見なすことができます。すべてのsのセットは、を満たすCustomer任意のsを所有するものにフィルターされます。次に、この結果セットは、満足のいくものを所有しているものにさらにフィルタリングされます。どちらの場合も同じである可能性があります。それは問題ではありません; ステップは互いに分離されています。Orderorder_id=9CustomerOrderorder_id=13Order

1回の呼び出しでオブジェクトからこの動作を取得する方法はいくつかあるかもしれませんが、それはDjangoのORMが使用されることを意図した方法ではないようです。Q().filter()

于 2012-09-18T17:33:17.793 に答える