2017-10-17 24 views
0

Django QuerySet APIを使用して、同じ2つのテーブル/モデル間で複数の結合を実行するにはどうすればよいですか?説明のために、次のテストされていないコードを参照してください:私は特定の名前付きフィールドを持つデータパケットのリストを取得したいDjango:同じ1対多の関係で複数の結合を持つ単一のクエリ

class DataPacket(models.Model): 
    time = models.DateTimeField(auto_now_add=True) 

class Field(models.Model): 
    packet = models.ForeignKey(DataPacket, models.CASCADE) 
    name = models.CharField(max_length=25) 
    value = models.FloatField() 

。私はこのような何か試してみました:

pp = DataPacket.prefetch_related('field_set') 
result = [] 
for p in pp: 
    o = { 
     f.name: f.value 
     for f in p.field_set.all() 
     if f.name in ('latitude', 'longitude') 
    } 
    o['time'] = p.time 
    result.append(o) 

をしかし、私は私が欲しい緯度と経度のフィールド以外の他の分野の多くのパケットの数百〜数千で働いているので、これは非常に非効率的であることが証明されました。

datapacketテーブルから異なる行のfieldテーブルへの2つの内部結合を実行する効率的なSQLクエリに変換するDjango QuerySet呼び出しがありますか?

from django.db import connection 

with connection.cursor() as cursor: 
    cursor.execute(''' 
     SELECT p.time AS time, f1.value AS lat, f2.value AS lon 
     FROM myapp_datapacket AS p 
     INNER JOIN myapp_field as f1 ON p.id = f1.packet_id 
     INNER JOIN myapp_field as f2 ON p.id = f2.packet_id 
     WHERE f1.name = 'latitude' AND f2.name = 'longitude' 
    ''') 
    result = list(cursor) 

をしかし本能があれば、低レベルのDB APIを使用しないように私に語った次のように私は(Djangoアプリケーションがmyapp命名されたと仮定した場合)(説明のために、再び、未テストコード)、生のSQLでそれを行うことができます私はそうする必要はありません。私のSQLコードがDjangoがサポートしているすべてのDBMと互換性がないかもしれない、あるいは私がDjango APIを誤解しているよりもSQLコマンドを誤解してデータベースを壊す危険があるように感じるかもしれない電話など

+0

[this](https://stackoverflow.com/questions/17375997/django-inner-join-queryset)と[this](https://stackoverflow.com/questions/42984676/django)をご覧ください。 -equivalent-for-sql-query-using-inner-join-clause)を使用します。同様の質問へのリンク。 – noes1s

+0

@ noes1s最初のリンクは、AからBへの内部結合の方法と、BからCへの内部結合の方法を尋ねています.2番目のリンクは、非遅延読み込みの特定のDjangoモデルフィールドのみをマークする方法を尋ねます。これらのどちらも私が求めているものには触れません。私はAからBへ2回参加したい:Aの同じ行、Bの異なる行 –

+0

生のSQLクエリを実行できましたか? – noes1s

答えて

0

お試しくださいPerforming raw SQL queries djangoで。同様にselect related in raw request。生のクエリに

プリフェッチ:

from django.db.models.query import prefetch_related_objects 
raw_queryset = list(raw_queryset) 
prefetch_related_objects(raw_queryset, ['a_related_lookup', 
'another_related_lookup', ...]) 

あなたの例:生のクエリセットでprefetch_relatedの

from django.db.models.query import prefetch_related_objects 
raw_DataPacket = list(DataPacket.objects.raw) 
pp = prefetch_related_objects(raw_DataPacket, ['field_set']) 

例:

モデル:

class Country: 
    name = CharField() 
class City: 
    country = models.ForeignKey(Country) 
    name = models.CharField() 

prefetch_relate d:

from django.db.models.query import prefetch_related_objects 
#raw querysets do not have len() 
#thats why we need to evaluate them to list 
cities = list(City.objects.raw("select * from city inner join country on city.country_id = country.id where name = 'london'")) 
prefetch_related_objects(cities, ['country']) 

答えは次のとおりです。djangoproject - performing raw queries | Related Stackoverflow Question | Google docs question

+0

また、テーブルAの各行について、テーブルBの2行を正確に選択するために、これをどのように使用するのかよくわかりません。現在、データベースカーソルと生のSQLを使ってどのように行っているかを表示するために質問を更新しました。 –

関連する問題