Django:随机排序(order_by('?'))进行额外查询

时间:2014-09-21 16:03:52

标签: django caching

以下是django中的示例代码。

[案例1]

views.py

from sampleapp.models import SampleModel
from django.core.cache import cache

def get_filtered_data():

    result = cache.get("result")

    # make cache if result not exists
    if not result:
         result = SampleModel.objects.filter(field_A="foo")
         cache.set("result", result)

    return render_to_response('template.html', locals(), context_instance=RequestContext(request))

template.html

  {% for case in result %}
  <p>{{ case.field_A}}</p>
  {% endfor %}

在这种情况下,在生成缓存后没有生成查询。我通过 django_debug_toolbar 检查了它。


[案例2]

views.py - 添加了一行result = result.order_by('?')

from sampleapp.models import SampleModel
from django.core.cache import cache

def get_filtered_data():

    result = cache.get("result")

    # make cache if result not exists
    if not result:
         result = SampleModel.objects.filter(field_A="foo")
         cache.set("result", result)

    result = result.order_by('?')

    return render_to_response('template.html', locals(), context_instance=RequestContext(request))

template.html - 与之前的相同

在这种情况下,即使我缓存了已过滤的查询,它也生成了新的查询。


如何在没有额外查询集的情况下调整随机排序?

  • 制作缓存时我无法放order_by('?')。 (例如result = SampleModel.objects.filter(field_A="foo").order_by('?')) 因为它甚至可以缓存随机顺序。

  • 是否与' django queryset是懒惰的有关?

提前致谢。

1 个答案:

答案 0 :(得分:7)

.order_by在数据库级别执行排序。

这是一个例子。我们在var results中存储了lasy queryset。尚无任何疑问:

results = SampleModel.objects.filter(field_A="foo")

例如,通过迭代来触摸results

for r in results:  # here query was send to database
    # ...

现在,如果我们再次这样做,不会尝试数据库,因为我们已经有了这个确切的查询:

for r in results:  # no query send to database
    # ...

但是,当您应用.order_by时,查询将会有所不同。所以,django必须向数据库发送新请求:

for r in results.order_by('?'):  # new query was send to database
    # ...

<强>解决方案

当您在django中执行查询时,您知道,您将从该查询中获取所有元素(即,没有OFFSET和LIMIT),那么您可以在从数据库获取这些元素之后在python中处理这些元素。 / p>

results = list(SampleModel.objects.filter(field_A="foo"))  # convert here queryset to list

在该行进行了查询,您拥有results中的所有元素。

如果您需要获得随机顺序,请立即在python中执行:

from random import shuffle
shuffle(results)

之后,结果将具有随机顺序,而不会将其他查询发送到数据库。