【问题标题】:Django Manager.values() returns a mysterious NoneDjango Manager.values() 返回一个神秘的 None
【发布时间】:2015-01-12 22:06:27
【问题描述】:

Django 1.7.1、MySQL 5.6、Python 2.7.8

我有一个类 Test 有几千个成员对象。它仅从具体的基类继承时间、日期和 id。 Test 类包含一个与不可为空的列相对应的属性。我们称之为color。当我跑步时

Test.objects.filter(date=date).values('color').distinct()

它忠实地返回一个看起来像的单例字典列表

[{'color': None}, {'color': u'yellow'}, {'color': u'clear'}, ... ]

确实,

>>> Test.objects.filter(date=date).count()
1650
>>> Test.objects.filter(date=date, color=None).count()
1650
>>> Test.objects.filter(date=date, color='clear').count()
4

这些返回值似乎与给定日期的 1650 个对象相矛盾,所有对象的颜色均为 None,但其中 4 个的颜色为“清晰”。其他颜色也返回良好的 int 值,对 DB 的检查确认它们是正确的,并且该列中根本没有 Nones。

None 的存在在其他地方给我带来了麻烦,当程序迭代这些值并获得 KeyError 时。

  • values() 是否会以某种方式微不足道地包含 None,即使它对于任何对象都不是真正的价值,甚至是不可能的?
  • 为什么None 在那里?
  • 我可以做些什么来避免它?
  • 【问题讨论】:

    • 颜色字段实际上是在那个模型上,还是另一个模型的 FK 或 M2M?
    • 无法从提供的代码中看出,但也许您有 order_by 问题?如果您的排序基于相关模型,则可以解释您如何在不可为空的字段上看到 None 值。请参阅文档中有关组合 values() 和 distinct() 的注释:docs.djangoproject.com/en/1.7/ref/models/querysets/…
    • @DanielRoseman 它在那个模型上。但是既然你提到它,日期字段一个外键。这可能有关系吗?
    • @dylrei 所以我没有明确地按任何东西排序,但我想某处可能有一个隐含的排序。您能解释一下“这可以解释您如何在不可为空的字段上看到 None 值”吗?我已经阅读了该部分和该注释,但除了包罗万象的“意外结果”之外,我看不出它与我得到的结果有何关系。在那种情况下,我仍然不明白如何为什么会发生这种情况。谢谢!我还应该提供哪些其他信息来帮助回答这个问题?
    • @WAF 您的代码正在与对象交互,但这些对象正在执行 SQL 代码。即使您只对查看一列感兴趣,您的基础 SQL 也可能正在使用连接……因此,即使您正在抑制大多数列,您也正在查看由多个列创建的效果。将这两个打印到控制台,看看你得到了什么:Test.objects.filter(date=date, color=None).query Test.objects.filter(date=date).values('color').distinct()。查询

    标签: python mysql django-admin nonetype


    【解决方案1】:

    如果 date 是外键(根据 cmets),那可能是问题的根源。

    我希望基础查询首先在此关系的“一”侧进行过滤,并且其中一些记录在“多”侧不匹配。那些不匹配的记录是您的初始结果集的一部分,因此对于某些行数,您会得到 None 的颜色。

    这有点杂乱无章,但您可以通过这种方式排除那些不匹配的记录:

    Test.objects.filter(date=date).exclude(color=None).values('color').distinct()
    

    或者是时候重新审视一下您的模型设计了。从这里很难知道。

    【讨论】:

    • 确实,显示的 SQL 显示子表和父表存在 INNER JOIN,导致 parent 切片包含的行数与其他对象类型。您的 exclude() 解决方案确实可以通过在末尾添加 WHERE...NOT 子句来工作。如果该条件在 SELECT 子查询中,SQL 会运行得更快吗? (假设父子比例很高。)谢谢!
    • @WAF 我不认为会有很大的不同,但我不太了解这是如何实现的。您总是可以尝试几种不同的策略并确定响应时间。也可以尝试 DateModel.objects.filter(date=date).test_set 看看是否效果更好(不确定你的“日期”模型被称为什么)。
    猜你喜欢
    • 1970-01-01
    • 2019-12-01
    • 2018-09-18
    • 2011-03-03
    • 2015-03-11
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多