2

我有一個Order模型和order_event模型。每個order_event都有一個可以訂購的外鍵。所以從一個訂單實例我可以得到:myorder.order_event_set。我想獲得所有訂單的清單,但我希望它們按最後一次活動的日期排序。像這樣的聲明的工作原理是最新的事件日期排序:按照相關模型子集的最新實例對django queryset進行排序

queryset = Order.objects.all().annotate(
    latest_event_date=Max('order_event__event_datetime') 
    ).order_by('latest_event_date') 

不過,我真正需要的是事件的子集的最新日期排序的所有訂單的列表。例如,我的事件分爲「調度」,「處理」等,所以我應該能夠獲得按最新調度事件排序的所有訂單的列表。這個Django文檔(https://docs.djangoproject.com/en/dev/topics/db/aggregation/#filter-and-exclude)顯示瞭如何使用過濾器獲取最新的計劃事件,但是這排除了沒有計劃的訂單事件。

我想我可以將過濾後的查詢集與包含缺少排定事件的那些訂單的查詢集合在一起......但我不太確定如何執行此操作。我看到與使用Python列表的答案,但它會更加有用有適當的Django的查詢集(即與分頁視圖等)

編輯回覆:意見/建議

class Order(models.Model): 
    desc = models.CharField(max_length=30) 

class Order_event(models.Model): 
    order = models.ForeignKey(Order) 
    event_datetime = models.DateTimeField(auto_now_add = True) 

而且,我不介意在多個聲明中這樣做。此外,排序等通過python而不是orm是可以的,因爲我沒有處理大量的數據集。如果可能的話,我寧願遠離SQL,因爲你提到的原因。組合單獨的排序查詢集似乎很有前途,但我陷入困境。

+1

如果您提供相關型號,會更容易理解 – acjay

+0

這些型號不是必需的,我完全理解您的要求。不知道是否可能,但不幸的是...至少不是純粹的ORM代碼。 – Greg

回答

1

好的,我認爲你可以用extra方法實現這一點,但據我所知,不能用純數據庫無關的orm來實現。這意味着你必須確保你的sql可以用於你正在使用的數據庫後端,並且要警惕django對錶名進行別名,但這也意味着你可以用一個查詢來完成所有工作。

沿着這些線路的東西應該工作:

latest_event_subquery = 'select max(event_datetime) ' \ 
         'from appname_order_event ' \ 
         'where appname_order_event.category="scheduling" and ' \ 
           'appname_order_event.event_id=appname_order.id' 
queryset = Order.objects.extra(select={'latest_event_date': latest_event_subquery}).order_by('latest_event_date') 

這是否有意義?

+0

我可以看到爲什麼這應該起作用,它確實似乎選擇了正確的查詢集(即,所有的訂單;沒有被過濾掉)。然而,latest_event_date沒有返回任何我知道有「調度」事件的訂單。我不完全確定爲什麼。我會一直試着去看看爲什麼,因爲這似乎是解決這個問題的唯一方法。 – rsp

+0

你使用的是什麼數據庫後端? – Greg

+0

另外,你可以粘貼'str(queryset.query)'的輸出嗎? – Greg

0

格雷格的答案很棒,我用了一段時間。但是,我想訪問latest_event的其他字段。所以,我結束了存儲latest_event作爲秩序的領域:

# The latest event 
latest_event = db.ForeignKey('whateverapp.Event', editable=False, null=True) 

然後我設置了一個信號,重新計算後的最新事件保存:

@receiver(post_save, sender=Event) 
def visit_calculate_latest(sender, instance, **kwargs): 
    """Recalculate latest event""" 
    instance.parent.latest_event = instance.parent.get_latest_event() 

其中get_latest_event()做了查詢:

def get_latest_event(self): 
    """Return most recent event or None.""" 
    try: 
     return Event.objects.filter(
      parent=self.id).order_by('-event_date', '-id')[0] 
    except IndexError: 
     return None 

現在我可以通過latest_event__whatever過濾:

return qs.filter(qobjs).order_by('-latest_event__event_date', 
     '-latest_event__pk') 
相關問題