【问题标题】:How can I test that Django QuerySets are ordered by PK ascending如何测试 Django QuerySet 是否按 PK 升序排序
【发布时间】:2014-06-15 22:39:51
【问题描述】:
class Foo(models.Model):
    name = models.CharField(max_length=10)

    class Meta(object):
        ordering = ('pk', )

我想测试此排序是否按预期工作。

def test_respect_ordering(self):
    Foo.objects.create(name="bar", pk=2)
    Foo.objects.create(name="baz", pk=1)
    results = Foo.objects.all()
    self.assertEqual("baz", results[0].name)
    self.assertEqual("bar", results[1].name)

尽管这可以按我的预期工作,但无论 Meta 类或其中定义的 ordering 属性如何,我的测试都通过了。有什么方法可以测试这段代码是否重要?

我为什么要测试这个? 我的测试在 SQLite 中运行,但生产在 mysql 中。希望有一天,我们会使用更好的 RDMBS,并且可能不会通过所有这些 RDMBS 的 PK 返回结果。

Django docs 表示排序不会自动发生。

【问题讨论】:

  • 如果你设置ordering = ('name', ),你的测试应该会失败,不是吗?
  • 那会失败,但从 Meta 中删除它不会失败,这就是我想要证明的......
  • 从 Meta 中删除它意味着您的数据库将默认按 pk 排序,所以我并不惊讶它通过了...
  • 我喜欢这种做法stackoverflow.com/a/51939953/1649917 - 检查类的元组件是否包含您期望的顺序

标签: python django


【解决方案1】:

如果您在Meta 类中省略ordering 属性,生成的SQL 查询将没有ORDER BY 子句(好吧,无论如何在1.4 中)。这意味着您不能依赖行的顺序。

无序的 SQL 查询通常有一个看起来有意义的顺序。这是因为查询计划很可能会使用索引来减少查询时间,并且索引可以在无序查询的行顺序中发挥重要作用。除非另有说明,否则由 Django 模型生成的表将仅在主键上具有索引,因此通常“无序”顺序与按主键排序时的顺序非常相似。

但是,这里绝对不能保证,不能依赖这个命令。查询计划很大程度上取决于数据库引擎,对于同一引擎上非常相似的查询,它甚至会发生巨大变化。

如果你想要一个特定的顺序,你应该明确指定你想要的顺序。这是保证特定订单的唯一可靠方法。

【讨论】:

  • 是的,这正是我将它添加到我的 Meta 中的原因。但是如何通过测试证明有必要呢?
  • 我不能给你任何明确的答案,这取决于太多的因素。您必须为您的特定设置找到一个反例。每次数据更改(插入、更新、删除)都会增加表的复杂性并增加意外结果顺序的可能性。
猜你喜欢
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 2012-07-30
  • 1970-01-01
相关资源
最近更新 更多