2014-11-29 2 views
3

장고 모델에서 임의의 여러 객체를 가져와야합니다.Django에서 임의의 여러 객체를 가져올 때 쿼리 세트는 어떻게 작동합니까?

은 내가 입력하여 모델 사람에서 하나 개의 임의 객체를 얻을 수 있습니다 알고

person = Person.objects.order_by('?')[0] 

그런 다음, 나는이 작업을 수행 단순히 수있는 말 How to get two random records with Django에 제안을 보았다 그러나

people = Person.objects.order_by('?')[0:n] 

, Django는 객체를 반환하는 대신 [0 : n]을 추가하자마자 QuerySet 객체를 반환합니다. 이것은 그들이이라고 나는 다음 검색어 세트가 평가 나는이 2 개의 다른 사람들을위한 FIRST_NAME과 LAST_NAME을 얻을

print(people[0].first_name, people[0].last_name) 

을 요구하는 경우 그 불행한 결과를 초래 (오른쪽?). 첫 번째 쿼리에서 반환 된 사람들의 실제 목록을 얻으려면 어떻게해야합니까?

나는이 시도 파이썬 3.4.0 장고 1.7.1

답변

0

시므온 포포프의 대답은 문제를 해결하지만, 어디에서 오는지 설명해 보자.

아마도 queryset은 게으르며 필요할 때까지 평가되지 않을 것입니다. 또한 전체 쿼리 세트가 평가되면 채워지는 내부 캐시도 있습니다. 하나의 객체가 하나의 쿼리 세트 (또는 step이 지정된 슬라이스, 즉 [0:n:2])에서 가져온 경우 장고는이를 평가하지만 결과는 캐시되지 않습니다.

다음 두 가지 예를 보자

예는 첫 번째 항목에 액세스 할 때 2

>>> people = Person.objects.order_by('?')[0:n] 
>>> for person in people: 
>>>  print(person.first_name, person.last_name) 
# first and last name are properly matched 

예 1에서의 검색어 아직 평가되지 않습니다 1

>>> people = Person.objects.order_by('?')[0:n] 
>>> print(people[0].first_name, people[0].last_name) 
# first and last name of different people 

예. 캐시되지 않으므로 첫 번째 항목에 다시 액세스하면 데이터베이스에서 다른 쿼리가 실행됩니다.

두 번째 예제에서는 전체 queryset을 반복 할 때 평가됩니다. 따라서 캐시가 채워지고 반환 된 항목의 순서를 변경하는 추가 데이터베이스 쿼리가 없습니다. 이 경우 이름이 서로 올바르게 정렬됩니다.

전체 쿼리 세트를 평가하는 방법은 a.o.입니다. 반복, list(), bool()len(). 이 방법들간에 약간의 차이점이 있습니다. 모두가 원하는 경우 쿼리 세트가 캐시되어 있는지 확인하려면

>>> people = Person.objects.order_by('?')[0:n] 
>>> bool(people) 
True 
>>> print(people[0].first_name, people[0].last_name) 
# matching names 
+0

이것은 매우 이상하게 보입니다. 여러분은 인수를 사용하여 함수를 호출하고 인수의 동작을 수정할 수 있습니다.함수가 쿼리 집합에이 효과를 줄지 결정하는 방법이 있습니까? 비슷한 성질을 가진 queryset과 같은 클래스가 더 있습니까? – Gunnar

+0

@Gunnar : 실제로 이것은 프로그래밍에서 일반적인 개념입니다. '가변적 인'객체라고합니다. 예 : 튜플은 변경 될 수 없으며 (불변), 각 변이는 복사본을 반환하지만 목록은 변경 가능하며'append '와 같은 함수는 실제로 목록 인스턴스 자체를 변경합니다. 'append (list, item) '대신에'list.append (item)'이라는 사실은 순수하게 접근성을 높이고 전역 네임 스페이스를 어지럽히는 것을 방지하기위한 것입니다. 일부 기능 ('bool()')은 캐싱이 어떻게 구현 되었기 때문에 처음에는 관련이없는 속성 (순서)에 영향을주기 때문에 유일하게 고유합니다. – knbk

0

를 사용하고 ...

people = [] 
for person in Person.objects.order_by('?')[0:n]: 
    people.append(person) 
+1

감사합니다. 감사합니다. 나는 또한 단순히 people = list (Person.objects.order_by ('?') [0 : n])가 작동한다는 것을 발견했다. – Gunnar

+0

당신의 솔루션은 더 좋습니다 ...하지만 내 마음 속에 처음입니다 : D – simopopov

관련 문제