tastypie在使用限制偏移量

时间:2015-08-12 09:43:26

标签: python django tastypie django-orm

我在tastypie中使用以下资源:

class ChoiceResource(LtgModelWithUuidResource):
    """
    Resource for the choice model
    """
    explanation = fields.ForeignKey(MultiLangTextFieldResource,attribute='explanation',full=True,null=True,
                                    use_in=DisableOnPatch())
    question = fields.ForeignKey('ltg_backend_app.base.api.question.QuestionResource',attribute='question',
                                 use_in=DisableOnPatch())
    keywords = fields.ManyToManyField(XrayResource,attribute='keywords',null=True,
                                      use_in=DisableOnPatch())

    class Meta(LtgResource.Meta):
        queryset = Choice.objects.select_related('explanation','question').\
            all().prefetch_related('keywords')

        allowed_methods = ['get']
        authentication = ApiKeyAuthentication()
        authorization = Authorization()
        order_by = ['id',]

问题:

查询

  

API / V1 /选择/限= 100安培;偏移量= 200

结果中包含 id = 615 的选项。

查询

  

api / v1 / choice /?limit = 100& offset = 2400

id = 615 的选择正在返回重新

  • api返回的total_count是正确的(6010个对象)。

可能的原因:

检查生成的SQL查询时,生成的SQL中没有ORDER BY,但设置了OFFSETLIMIT

引用 Postgresql 文档:

  

使用LIMIT时,最好使用ORDER BY子句将结果行限制为唯一顺序。否则你会得到一个不可预知的查询行的子集---你可能会要求第十到第二十行,但第十到第二十行是什么排序?除非您指定ORDER BY

,否则排序未知      

查询优化器在生成查询计划时会考虑LIMIT,因此您很可能会得到不同的计划(产生不同的行顺序),具体取决于您为LIMIT和{{1}提供的内容}}。因此,使用不同的OFFSET / LIMIT值来选择查询结果的不同子集将产生不一致的结果,除非您使用OFFSET强制执行可预测的结果排序。这不是一个bug;这是SQL不承诺以任何特定顺序传递查询结果这一事实的固有后果,除非ORDER BY用于约束订单。

我发现的解决方案:

我已将ORDER BY添加到查询集中,现在看起来像这样:

order_by

问题:

  • 我不确定我在这里遗漏了什么,或者我做错了什么。 任何澄清将不胜感激。

  • 我认为,我不应该在django查询集或url查询参数中包含Choice.objects.select_related('explanation','question').\ all().prefetch_related('keywords').order_by('id) 以使其工作,或者至少它没有在tastypie docs。

感谢。

2 个答案:

答案 0 :(得分:0)

ID通常以1开头。但情况并非总是如此。无论如何,默认排序将按其插入的顺序排列,因此这是预期的行为。

如果您想覆盖它,您可以像前面提到的那样在ordering类中设置Media参数。或者您也可以在GET查询中传递order_by

答案 1 :(得分:0)

在您的特定情况下,您需要在Queryset中使用.order_by,因为字段id并非Tastypie资源的一部分。只有Django模型。 参考:Tastypie source

general 中,最好的做法是将字段排序为尽可能靠近数据。如果该字段存在于Django模型中-请使用允许最佳SQL调用的queryset对其进行排序。但是,如果该字段是根据Tastypie资源计算的,则让Tastypie的order_by处理它。