2011-01-11 5 views
1

사용자 지정 순서로 내 테이블에서 항목을 선택하고 싶습니다. 에 SQL을 지정하고 주문을 지정하지 않으면 오름차순 기본 키가 사용되므로 'IN'순서가 손실됩니다.Django에서 같은 순서로 IN을 선택 하시겠습니까?

이제
SELECT * FROM table WHERE id IN (118,17,113,23,72) ORDER BY FIELD(id,118,17,113,23,72) 

, 장고 내에서이 요청을 코드에 내가 할 수있는 방법은 다음과 같습니다 나는 하나가 'IN'질서를 유지하기 위해이 SQL 요청을 사용할 수 있도록 읽어? 참고 : SQL에서 작업을 수행하기 때문에 .in_bulk() 쿼리 세트 메서드를 사용하고 싶지 않습니다.

답변

2

Django 1.2 이상에서는 raw() 관리자 메소드를 사용하면됩니다.

ids = "118,17,113,23,72" 
results = MyModel.objects.raw('SELECT * FROM myapp_mymodel WHERE `id` IN (%s) ' 
           'ORDER BY FIELD (id, %s)' % (ids, ids)) 

몇 가지 참고 사항 : 당신이 요소에 의해 주문에 대한 처리 매개 변수를 사용할 수 없기 때문에

  • 이, SQL 주입 공격에 잠재적으로 취약하다. ids 목록은 반드시 위생 처리해야합니다.

  • raw()은 일반 쿼리 세트와 같은 쿼리를 캐시하지 않으므로 반복 할 때마다 쿼리를 다시 평가합니다. 값이 두 번 이상 필요하면 먼저 list()으로 전화하십시오.

  • ORDER BY FIELD은 MySQL 관련 확장 프로그램입니다.

  • 최종 요청이 의미가 없습니다. in_bulk()은 SQL을 사용하여 작업을 수행합니다. 그러나 어쨌든 귀하의 쿼리에 적합하지 않습니다.

+0

in_bulk()에 동의하면 IN SQL 절을 사용하십시오. 좋은 설명! – santiagobasulto

0

나는 이것을 시도했다 : IN을 SQL 절을 사용합니까 렸기 때문에 어쨌든

from django.db.models import Q 
# first you get the IDs 
ids = [1,2,3,4,5] 
# after that you can get a list of Q objects 
q_objects = [Q(id=id) for id in ids] 
# then you need to combine all the Q objects 
# I'll use a functional approach, an operation called fold_left but you can use a for instead 

# i need the first element 
first_q = q_objects.pop() 
final_q = reduce(lambda total,q: total | q,q_objects,first_q) 
# now you can get the result 
MyModel.objects.filter(q) 
#if you need an order simply append order_by 
MyModel.objects.filter(q).order_by(something) 

in_bulk에 의해 수행 된 쿼리를보십시오. 당신은 단지 django_toolbar 사용할 수 물론

SELECT [fields] 
FROM [my_table] WHERE [my_model].`id` IN (1, 2) 

:

python manage.py shell 


>>> from testapp.models import Car 
>>> from django.db import connection 
>>> cars = Car.objects.in_bulk([1,2]) 
>>> my_queries = connection.queries 
>>> my_queries[0]['sql'] 

이것은 SQL 결과입니다 :이 장고 1.3와 MySQL과 테스트입니다.

관련 문제