【问题标题】:Cannot filter a query once slice has been taken djangodjango 获取切片后无法过滤查询
【发布时间】:2021-03-05 09:08:10
【问题描述】:

跟进:

AutoField should be present but it's not (django)?

相关:

"Cannot update a query once a slice has been taken". Best practices?

我不需要过滤对象,只按日期排序并选择最近的一个:

def get_latest_currency(self):
    """
    Return most up to date value
    """
    up_to_date_currency = Currency.objects.order_by('-currency_value_in_dollars_date')[:1]

    if not up_to_date_currency.exists():
        # No objects yet; fetch currencies
        update_coins_table()

    return Currency.objects.order_by('-currency_value_in_dollars_date')[:1]

up_to_date_currency 已正确初始化;最后一行给出:

    assert not self.query.is_sliced, \
AssertionError: Cannot filter a query once a slice has been taken.

这段代码代表一个视图(我想返回一个普通的 JSON 对象(这是一个 REST 端点))。为什么 django 在只使用切片时抱怨过滤器?

get_latest_currency 是端点的名称:

import sys

from django.urls import path
from . import views

app_name = 'manage_crypto_currency'
urlpatterns = [
    path('get_currency/', views.get_latest_currency, name='index'),
]

堆栈跟踪:

Internal Server Error: /get_currency/
Traceback (most recent call last):
  File "C:\projects\crypto-currency-board\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\projects\crypto-currency-board\venv\lib\site-packages\django\utils\deprecation.py", line 116, in __call__
    response = self.process_response(request, response)
  File "C:\projects\crypto-currency-board\venv\lib\site-packages\django\middleware\clickjacking.py", line 26, in process_response
    if response.get('X-Frame-Options') is not None:
  File "C:\projects\crypto-currency-board\venv\lib\site-packages\django\db\models\query.py", line 418, in get
    clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
  File "C:\projects\crypto-currency-board\venv\lib\site-packages\django\db\models\query.py", line 942, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "C:\projects\crypto-currency-board\venv\lib\site-packages\django\db\models\query.py", line 954, in _filter_or_exclude
    assert not self.query.is_sliced, \
AssertionError: Cannot filter a query once a slice has been taken.

尝试将对象包裹在 HttpReponse() 周围:

return HttpResponse(Currency.objects.order_by('-currency_value_in_dollars_date')[:1], content_type='application' '/json')

这可行,但由于某种原因,只返回了名称。

【问题讨论】:

  • 你在哪里使用get_latest_currency?看起来您过滤了get_latest_currency结果
  • 你能展示完整的 ltraceback 吗?
  • @Williem 这是一个风景
  • @Dmitry 添加了堆栈跟踪
  • 问题是你把这个函数当作一个view,但是一个view应该返回一个HttpResponse

标签: python python-3.x django


【解决方案1】:

您正在返回 QuerySet 作为 view 的结果,但 view 不能返回 QuerySet。中间件旨在将其转换为 HTTP 响应,从而导致错误。

因此您的视图需要返回一些HttpResponse [Django-doc]。一个非常简单的响应是QuerySetstr(…)

def get_latest_currency(self):
    up_to_date_currency = Currency.objects.order_by('-currency_value_in_dollars_date')[:1]

    if not up_to_date_currency.exists():
        # No objects yet; fetch currencies
        update_coins_table()

    qs = Currency.objects.order_by('-currency_value_in_dollars_date')[:1]
    # …
    return HttpResponse(str(qs))

您当然可以返回更复杂的结果,例如通过渲染模板或返回序列化程序的结果。

例如如果你想序列化最后一个对象,你可以使用:

from django.http import JsonResponse
from django.core.serializers import serialize
from json import loads as jloads

def get_latest_currency(self):
    up_to_date_currency = Currency.objects.order_by('-currency_value_in_dollars_date')[:1]

    if not up_to_date_currency.exists():
        # No objects yet; fetch currencies
        update_coins_table()

    cr = Currency.objects.latest('-currency_value_in_dollars_date')
    data = serialize('json', [cr])
    return JsonResponse({'data' : jloads(data)})

【讨论】:

  • 当使用 str(query_results) 我得到 ]> 。
  • @Sebi:没错,但关键是你可以返回QuerySet作为视图的结果。 HTTP 响应始终是 文本,因此您可以将其序列化为 JSON blob 等,但不能返回 QuerySet、模型对象等。
  • @Sebi:您可以使用JsonResponse 和Django 序列化来JSON 序列化数据。
猜你喜欢
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 2013-07-20
  • 2015-10-26
相关资源
最近更新 更多