2017-10-17 4 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) 

을하지만 내가 원하는 위도와 경도 필드 외에 다른 분야의 많은 수백 패킷 수천 함께 일하고 있어요 때문에 매우 비효율적 입증되었습니다.

datapacket 테이블에서 다른 행의 field 테이블로 두 개의 내부 조인을 수행하는 효율적인 SQL 쿼리로 변환되는 Django QuerySet 호출이 있습니까? 없는 낮은 수준의 DB API를 경우를 사용하는

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) 

그러나 본능 알려줍니다 : (다시, 검증되지 않은 설명을 위해 코드) (장고 응용 프로그램이 myapp라는 가정)는 다음과 같이 나는 원시 SQL 함께 할 수 있습니다 나는 그렇게 할 필요가 없다. 가능한 이유는 내 SQL 코드가 Django가 지원하는 모든 DBM과 호환되지 않을 수도 있고, 장고 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 절). 비슷한 질문에 대한 링크. – noes1s

+0

@ noes1s 첫 번째 링크는 A에서 B로 내부 결합하는 방법을 묻고 B에서 C로 내부 결합합니다. 두 번째 링크는 지연되지 않은로드를 위해 특정 Django 모델 필드 만 표시하는 방법을 묻습니다. 이들 중 어느 것도 제가 요구하는 것을 만질 수 없습니다. A에서 B로 두 번 가입하고 싶습니다 : A에서 같은 행, 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', ...]) 

귀하의 예 : 원시의 검색어와 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의 두 행을 정확하게 선택하는 방법을 모르겠습니다. 데이터베이스 커서와 원시 SQL을 사용하여 현재 수행하는 방법을 보여주기 위해 제 질문을 업데이트했습니다. –