我需要从Django模型中获取多个随机对象。
我知道我可以通过键入:
从模型Person中获取一个随机对象person = Person.objects.order_by('?')[0]
然后,我在How to get two random records with Django中看到了一些建议,我可以通过以下方式做到这一点:
people = Person.objects.order_by('?')[0:n]
但是,只要我添加[0:n],Django就不会返回对象,而是返回一个QuerySet对象。如果我要求
,这会导致不幸的后果print(people[0].first_name, people[0].last_name)
我为2个不同的人获取first_name和last_name,因为QuerySets在被调用时被评估(对吗?)。如何获取第一个查询返回的实际人员列表?
我正在使用Python 3.4.0和Django 1.7.1
答案 0 :(得分:0)
试试这个......
people = []
for person in Person.objects.order_by('?')[0:n]:
people.append(person)
答案 1 :(得分:0)
Simeon Popov的回答解决了这个问题,但让我来解释它的来源。
您可能知道查询集是惰性的,在有必要之前不会进行评估。它们还有一个内部缓存,一旦评估了整个查询集,就会被填充。如果只从查询集(或指定了step
的切片,即[0:n:2]
)中获取单个对象,Django会对其进行评估,但结果不会被缓存。
采取以下两个例子:
示例1
>>> people = Person.objects.order_by('?')[0:n]
>>> print(people[0].first_name, people[0].last_name)
# first and last name of different people
示例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中,当您访问第一个项目时,尚未评估查询集。它不会被缓存,因此当您再次访问第一个项目时,它会在数据库上运行另一个查询。
在第二个示例中,循环遍历整个查询集。因此,缓存已填满,并且不会有任何其他数据库查询会更改返回项的顺序。在这种情况下,名称彼此正确对齐。
评估整个查询集的方法是a.o.迭代,list()
,bool()
和len()
。这些方法之间存在一些细微差别。如果您只想确保查询集被缓存,我建议使用bool()
,即:
>>> people = Person.objects.order_by('?')[0:n]
>>> bool(people)
True
>>> print(people[0].first_name, people[0].last_name)
# matching names