Qオブジェクトと外部キーに関するパズル
-
06-07-2019 - |
質問
次のようなモデルがあります:
class Thing(models.Model):
property1 = models.IntegerField()
property2 = models.IntegerField()
property3 = models.IntegerField()
class Subthing(models.Model):
subproperty = models.IntegerField()
thing = modelsForeignkey(Thing)
main = models.BooleanField()
各フィルターの形式が{'type':something、 'value':x}であるフィルターのリストが渡される関数があります。この関数は、結果のセットを返し、すべてのフィルターをまとめて返す必要があります。
final_q = Q()
for filter in filters:
q = None
if filter['type'] =='thing-property1':
q = Q(property1=filter['value'])
elif filter['type'] =='thing-property2':
q = Q(property2=filter['value'])
elif filter['type'] =='thing-property2':
q = Q(property3=filter['value'])
if q:
final_q = final_q & q
return Thing.objects.filter(final_q).distinct()
各サブシングには、ブール値プロパティ「main」があります。すべてのものには、main == Trueであるサブモノが1つだけあります。
main == True
および subproperty == filter ['value']
作成中の Q
オブジェクトの一部としてこれを実行できますか?そうでない場合は他に?新しいフィルターの前に取得するクエリセットは非常に大きくなる可能性があるため、結果をループ処理しない方法が必要です。
解決
Subthingsに明示的に" related_name"を指定すると、理解しやすくなります。事物との関係で
class Subthing(models.Model):
...
thing = models.ForeignKey(Thing, related_name='subthings')
...
今、 Django joinを使用しますQオブジェクトを構築する構文:
Q(subthings__main=True) & Q(subthings__subproperty=filter['value'])
逆リレーションシップのデフォルト名は「subthing_set」ですが、「subthings」などのより良い名前を付けるとわかりやすくなります。
他のヒント
使用(最初に final_q = Q()
の代わりに)
final_q=Q(subthing_set__main=True)
sub_vals = map(lambda v: v['value'], filters)
if sub_vals:
final_q = final_q & Q(subthing_set__subproperty__in=sub_vals)
必要なものが得られたら、ループを調整してsub_valsリストを作成し、ループの後に適用することもできます。
subthing_setは、関連するSubthingsにアクセスするためにThingに追加された関連フィールドを自動的に追加します。
別の関連する名前を割り当てることができます。例:
thing=models.ForeignKey(Thing,related_name='subthings')
所属していません StackOverflow