2017-10-17 59 views
0

使用Django QuerySet API,如何在同一個兩個表/模型之間執行多個聯接?出於說明目的,請參閱以下未經測試的代碼:Django:在同一個一對多關係中具有多個聯接的單個查詢

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) 

但是,這已經被證明非常低效的,因爲我有數百至數千的數據包的工作有很多,除了緯度和經度領域我想等領域。

是否有一個Django QuerySet調用轉換爲執行兩個內部聯接從datapacket表到field表不同的行上的內部聯接?我可以用原始的SQL這樣做,如下(假設Django的應用程序名爲myapp)(再次,爲了說明未經測試的代碼):

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如果我不必這樣做。支持這種做法的可能原因可能是我的SQL代碼可能與Django支持的所有DBM不兼容,或者我覺得由於誤解了SQL命令而導致數據庫被貶低的風險比我誤解Django API呼叫等。

+0

看看[this](https://stackoverflow.com/questions/17375997/django-inner-join-queryset)和[this](https://stackoverflow.com/questions/42984676/django換算換使用-內SQL查詢-聯接子句)。鏈接到類似的問題。 – noes1s

+0

@ noes1s你的第一個鏈接詢問如何內從A加盟B,然後從內B到C.加入你的第二個鏈接問如何標記爲非延遲加載只有特定的Django模型領域。這些都不涉及我所要求的。我想從A地加入到B兩次:在同一行,在B. –

+0

不同的行,您可以執行原始SQL查詢? – noes1s

回答

0

嘗試在django Performing raw SQL queries。以及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', ...]) 

你舉的例子:使用原始的queryset 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的每一行我已經更新了我的問題,以顯示我目前如何使用該數據庫遊標和原始的SQL執行從表B中正好兩行。 –

相關問題