1

次のモデルがあるとしましょう。

class House(models.Model):
    address = models.CharField(max_length=255)

class Person(models.Model):
    name = models.CharField(max_length=50)
    home = models.ForeignKey(House, null=True, related_name='tenants')

class Car(models.Model):
    make = models.CharField(max_length=50)
    owner = models.ForeignKey(Person)

取得する必要があるとしましょう(奇妙なものですが):

  • 家に住んでいるか、「ジョン」という名前の人のリスト
  • 上記の人の車のリスト

私は2つの機能を持ちたいです:

  • get_tenants_or_johns(house)
  • get_cars_of_tenants_or_johns(house)

私はそれらを次のように定義することができます:

from django.db.models.query_utils import Q

def get_cars_of_tenants_or_johns(house):
    is_john = Q(owner__in=Person.objects.filter(name='John'))
    is_tenant = Q(owner__in=house.tenants.all())
    return Car.filter(is_john | is_tenant)

def get_tenants_or_johns(house):
    johns = Person.objects.filter(name='John')
    tenants = house.tenants.all()
    return set(johns) | set(tenants)

問題は、上記の例でロジックが繰り返されていることです。get_tenants_or_johns(house)私が返すことができれば、queryset私は次のように定義することができますget_cars_of_tenants_or_johns(house)

def get_cars_of_tenants_or_johns(house):
    return Car.objects.filter(owner__in=get_tenants_or_johns(house))

これを行うには、get_tenants_or_johns(house)クエリセットを他のコレクションに変換せずに、クエリセットの和集合を返す必要があります。

get_tenants_or_johns(house)SQLを含むクエリセットを返すように実装する方法がわかりませんUNION。それを行う方法はありますか?そうでない場合、私がやろうとしていることを達成するための別の方法はありますか?

4

2 に答える 2

9

2つのクエリセットの|演算子は、和集合を表す新しいクエリセットを返します。

関数は次のように変更する必要があります(set()ラッパーを削除しました):

def get_tenants_or_johns(house):
    johns = Person.objects.filter(name='John')
    tenants = house.tenants.all()
    return johns | tenants

そして、すべてが必要に応じて正確に機能します。

于 2013-01-09T15:12:26.993 に答える
0

あなたは家に住んでいるユーザーについて言及していますが、ユーザーモデルについては言及していません。

アプリケーションの構造をじっくりと検討する必要があると思います。おそらく、目標を達成するためのはるかに簡単な方法があります。

しかし、あなたの質問に答えるために、3つのヘルパー関数を設定しましょう。上で述べたように、Userクラスで何をしたいのかを概説していないので、houseこれらの関数に渡されるのはアドレスであると想定しました。

helpers.py

def get_johns(house):
    is_john = Person.objects.filter(name='John')
    return is_john

def get_cars_of_tenants(house):
    cars = Car.objects.filter(owner__home__address=house)
    return cars

def get_tenants(house):
    tenants = Person.objects.filter(home__address=house)
    return tenants

これで、組み合わせクエリごとにビューを作成できます。

views.py:

import helpers.py
from itertools import chain

def get_cars_of_tenants_or_johns(request, house):
    results = list(chain(get_cars_of_tenants(house), get_johns(house)))
    return render_to_response('cars_or_johns.html', {"results": results,})

def get_tenants_or_johns(request, house):
    results = list(chain(get_tenants(house), get_johns(house)))
    return render_to_response('tenants_or_johns.html', {"results": results,})

そして、これはさまざまな組み合わせのすべてに当てはまります。返さresultsれるのは、反復できるすべての一致のリストです。

于 2013-01-09T05:12:27.627 に答える