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

Che*_*mer 5 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))
Run Code Online (Sandbox Code Playgroud)

template.html

  {% for case in result %}
  <p>{{ case.field_A}}</p>
  {% endfor %}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,缓存生成后没有生成查询.我用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))
Run Code Online (Sandbox Code Playgroud)

template.html - 与上一个相同

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


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

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

  • 它与' django queryset是懒惰 '有关吗?

提前致谢.

sta*_*alk 10

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

这是一个例子.我们在var中存储了lasy queryset results.尚未进行任何查询:

results = SampleModel.objects.filter(field_A="foo")
Run Code Online (Sandbox Code Playgroud)

results例如,通过迭代来触摸它:

for r in results:  # here query was send to database
    # ...
Run Code Online (Sandbox Code Playgroud)

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

for r in results:  # no query send to database
    # ...
Run Code Online (Sandbox Code Playgroud)

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

for r in results.order_by('?'):  # new query was send to database
    # ...
Run Code Online (Sandbox Code Playgroud)

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

results = list(SampleModel.objects.filter(field_A="foo"))  # convert here queryset to list
Run Code Online (Sandbox Code Playgroud)

在该行进行查询并且您拥有所有元素results.

如果你需要获得随机顺序,现在在python中执行:

from random import shuffle
shuffle(results)
Run Code Online (Sandbox Code Playgroud)

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

  • 惊人的解决方案。Stack Overflow 的美妙之处在于我可以在超过 3 年半的答案中找到价值。我想知道 Django 是否有计划实现这样的东西。 (4认同)