基于最新子记录条件在Django中过滤模型

2 投票
4 回答
1357 浏览
提问于 2025-04-17 10:25

我有两个模型,像这样:

class Store(models.Model):
    name = models.CharField(max_length=255)

class Order(models.Model):
    store = models.ForeignKey(Store)
    date = models.DateTimeField(auto_now_add=True)
    success = models.BooleanField()

我想从Store模型中筛选出所有最新订单成功的记录,也就是说success == True

虽然看起来很简单,但我在使用ORM查询系统时遇到了问题,不知道该怎么做。

有人能帮忙吗?谢谢。

4 个回答

0

你可以通过一个查询来完成这个操作。

使用 .extra() 这个功能,可以在查询集中写出类似下面的SQL语句:

Store.objects.extra(where=['id in (select store_id from order where success = true)']) 
1

这只是一个想法,所以如果我说错了别打我哦 :)

我觉得你可以这样做:

# first annotate latest order to Store which returns new queryset, filter new qs
# by success = True
stores = Store.objects.annotate(Max('order__date')).filter(order__success=True)

老实说,这个还没经过测试。

2

我的方法是这样的:先做两个列表,第一个列表包含(商店ID,最后成功日期)的组合,第二个列表包含(商店ID,最后日期)的组合:

l_succ = stores.objects.filter( 
                       order__success = True 
                  ).annotate(
                       last_success=Max('order__date')
                  ).value_list (
                       'id', 'last_success'
                  )
#l_succ = [ (1, '1/1/2011'), (2, '31/12/2010'), ... ] <-l_succ result

l_last = stores.objects.annotate(
                       last_date=Max('order__date')
                  ).value_list (
                       'id', 'last_date'
                  )
#l_last = [ (1, '1/1/2011'), (2, '3/1/2011'), ... ]   <-l_last result

然后找出那些最后日期和最后成功日期相等的商店ID,这样你就得到了查询:

store_success_ids =  [ k[0] for k in l_succ if k in l_last ]
#store_success_ids = [1, 5, ... ]          <-store_success_ids result
#Cast l_last to dictionary to do lookups if you have a lot of stores.

result = Store.objects.filter( pk__in = store_success_ids)        

这个方法看起来很优雅,只用四行代码就能完成一个复杂的查询(但要求其实很简单)。需要说明的是,这个方法还没有经过测试。

撰写回答