【问题标题】:Django : random ordering(order_by('?')) makes additional queryDjango:随机排序(order_by('?'))进行额外查询
【发布时间】:2014-11-15 15:39:37
【问题描述】:

这是 django 中的示例代码。

[案例一]

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 is lazy'有关?

提前致谢。

【问题讨论】:

    标签: django caching


    【解决方案1】:

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

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

    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 中处理这些元素。

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

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

    如果你需要随机排序,现在就用python来做吧:

    from random import shuffle
    shuffle(results)
    

    之后,结果将具有随机顺序,无需向数据库发送额外的查询。

    【讨论】:

    • 哇,你建议的解决方案真的很棒。谢谢!
    • 惊人的解决方案。 Stack Overflow 的美妙之处在于我可以在 3 年半前的答案中找到价值。我想知道 Django 是否有计划实现这样的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多