2009-12-14 64 views
9

感謝來自另外一個問題一個非常有用的提示我學到我可以在模板切片它是這樣限制列表中值的數量:Django的模板片 - 倒車訂購

{% for comment in thread.comment_set.all|slice:":3" %} 

現在我想讓我評論的最後3個結果,所以我想出一個簡單的「:-3」或「-3」會做的伎倆,唉:

Caught an exception while rendering: Negative indexing is not supported. 

而且使用:

{% for comment in thread.comment_set.all|slice:":3" reversed %} 

不要這樣做,因爲如果我有5條評論,而不是1,2,3,它會以3,2,1順序顯示前三條。

有沒有什麼辦法可以顯示帖子的最後3條評論,而無需進入我的數據庫?我很樂意純粹使用模板系統。

SOLUTION

{% for comment in thread.comment_set.all|dictsortreversed:"created"|slice:"3" %} 

顯示最後三個拜我爲表的創建時間戳。

回答

11

Django的數據庫查詢懶洋洋地評估,所以thread.comment_set.all結果是一個QuerySet ,而不是一個列表。 QuerySet支持許多類似列表的函數,但不支持負切片,因此索引錯誤不是來自模板過濾器本身。 (如果您很好奇,QuerySet對象上的切片將轉換爲SQL語句中的limit子句,這就是您不能使用負數的原因)。

一般來說,Django鼓勵模板和模型的嚴格解耦; views.py模塊是您做任何需要知道數據庫模型和查詢集方法以將模型數據轉換爲模板的簡單變量和結構的工作的粘合劑。

在模板上運行相關查詢並不是您通常在Django模板中看到的,並且這有很好的理由。現在,對comment_set中的最後三個元素進行分片似乎很簡單。但請記住,數據庫不會以任何有保證的順序返回結果。這意味着,除了切片之外,您現在還需要添加一個order_by子句;根本無法在模板中表達這一點,也不應該這樣做。最好將視圖看作是模型和模板之間的翻譯,並讓這些面向數據庫的工作在那裏完成,而不是嵌入到HTML中。

在這種情況下,我會鼓勵你的有序片從視圖傳遞到您的模板:

# take first three sorted descending 
comments = thread.comment_set.order_by('-something')[:3] 

context = Context({'comments':comments}) 
return HttpResponse(tmplt.render(context)) 

如果必須在模板做切片,你真的不關心排序結果,將一個列表傳遞給模板。該slice過濾器會很樂意做負切片:

comments = list(thread.comment_set.all()) 
context = Context('comments':comments) 

在模板:

{% for comment in comments|slice:"-3:" %} 
+1

我喜歡我得到和修改的答案是,我實際上在拉我的線程表,然後從模板中拉出相應的註釋,以便Django正在完成提取正確註釋的工作。我會說我並不十分在意這樣一個事實,即它只將每一個評論都拉到切片上,所有的都保存爲3,它確實很好地工作,因爲它把它們全部拉出來,然後按照它們創建的日期對它們進行分類,然後將它們切掉。 – TheLizardKing 2009-12-14 03:11:21

+1

如果有一個我可以編寫的查詢可以提取X個線程和它們各自的*最後*三個評論,那麼我會是黃金。相反,我這樣做。 – TheLizardKing 2009-12-14 03:12:54

+0

如果可以的話,我會給你所有的+1: -/15 Rep :( – TheLizardKing 2009-12-14 03:13:27

9

我還沒有看到使用過於頻繁的dictsortreversed過濾器,並根據文檔需要一個關鍵的排序

{% for comment in thread.comment_set.all|dictsortreversed:"name"|slice:"3" %} 
+0

更改「名稱」爲「創建」做了訣竅,謝謝! – TheLizardKing 2009-12-14 02:23:16

0

你就不能把它傳遞給你的模板之前切片名單?

1

使用Comment類的Meta類的「ordering」屬性來設置所需的元素排序。

IMO模板不適合訂購您的數據集。訂購應在模型或視圖中完成。

0

如果查詢集已經按「創建」進行了排序,則可以將其顛倒過來。所以這是一個更快的解決方案。

{% for comment in thread.comment_set.all.reverse|slice:":3" %} 

此外,如果你不想以相反的順序。

{% for comment in thread.comment_set.all.reverse|slice:":3"|dictsort:"created" %} 

雖然應該遵循上述Jarrets哈迪諮詢和做的意見,所有的邏輯,而不是在模板中。

0

我需要這一點,並提出了一個更完整的解決方案,我認爲。希望人們發現它很有用。該視圖需要找到last inserted record (example here)的ID。你必須扭轉順序,並獲得最新的最後一條記錄的ID(PK),現在將成爲第一條記錄,現在很容易在堆的頂部找到;-)。計算你想要的下限id值,然後在最後使用這個運算符從最低到最新或最後一個條目進行排序... [n:m](我認爲這只是一個列表運算符),刪除不需要的記錄,然後按正常順序呈現。對於這裏的Django表例子是我的代碼:

def showLatestRels(request): 
    #This view shows the latest 15 entries in the Release table 
    LastInserted = Release.objects.order_by('-pk')[0] 
    UpperLimit = LastInserted.id 
    LowerLimit = UpperLimit - 15 
    RelTable = Release.objects.all() 
    tablevalslat = ReleaseTable(RelTable[LowerLimit:UpperLimit]) 
    RequestConfig(request).configure(tablevalslat) 
    return render(request, 'DCESrtap/latrels.html', {'tablevalslat': tablevalslat} 

很多方法可以做到這一點,看到Django docs Make/limit Queries
但不能讓dictsort思想工作....