2010-09-17 33 views
37

Tôi có một mô hình:Django Query sử dụng .order_by() và .latest()

class MyModel(models.Model): 
    creation_date = models.DateTimeField(auto_now_add = True, editable=False) 

    class Meta: 
     get_latest_by = 'creation_date' 

Tôi đã có một truy vấn trong quan điểm của tôi rằng đã làm như sau:

instances = MyModel.objects.all().order_by('creation_date') 

Và sau đó tôi muốn instances.latest(), nhưng nó sẽ không cho tôi ví dụ chính xác, trên thực tế nó đã cho tôi ví dụ đầu tiên. Chỉ khi tôi đặt order_by thành -creation_date hoặc thực sự đã xóa order_by khỏi truy vấn đã làm .latest() cho tôi ví dụ chính xác. Điều này cũng xảy ra khi tôi kiểm tra điều này bằng tay bằng cách sử dụng shell python manage.py thay vì trong khung nhìn.

Vì vậy, những gì tôi đã làm bây giờ là trong mô hình của Meta tôi đã liệt kê order_by = ['creation_date'] và không được sử dụng trong truy vấn, và hoạt động.

Tôi đã mong đợi .latest() để luôn trả lại phiên bản gần đây nhất dựa trên trường (ngày) (thời gian). Bất cứ ai có thể cho tôi biết liệu chính xác là .latest() có hoạt động lạ khi bạn sử dụng order_by trong truy vấn không?

Trả lời

64

Tôi đã mong đợi .latest() để luôn trả về phiên bản gần đây nhất dựa trên trường (ngày) (thời gian).

Các documentation nói rằng

Nếu của Meta mô hình mà bạn chỉ định get_latest_by, bạn có thể rời khỏi tranh cãi field_name để latest(). Django sẽ sử dụng trường được chỉ định trong get_latest_by theo mặc định.

Tất cả điều này có nghĩa là khi bạn bắn MyModel.objects.latest() bạn sẽ nhận được phiên bản mới nhất dựa trên trường ngày/giờ. Và khi tôi kiểm tra mã của bạn bằng cách sử dụng dữ liệu mẫu, nó thực sự đã làm.

Và sau đó tôi muốn instances.latest(), nhưng nó sẽ không cho tôi ví dụ chính xác, trên thực tế nó đã cho tôi ví dụ đầu tiên.

Bạn đã hiểu sai cách latest() hoạt động. Khi được gọi vào số MyModel.objects, nó trả về phiên bản mới nhất trong bảng . Khi được gọi trên bộ truy vấn , latest sẽ trả về đối tượng đầu tiên trong bộ truy vấn. Bộ truy vấn của bạn bao gồm tất cả các phiên bản của MyModel được yêu cầu bởi creation_date theo thứ tự tăng dần. Chỉ là tự nhiên khi đó latest trên truy vấn này phải trả lại đầu tiên hàng của bộ truy vấn. Điều này ngẫu nhiên xảy ra là hàng lâu đời nhất trong bảng .

Một cách để hiểu rõ hơn là xem truy vấn được kích hoạt cho latest.

Trường hợp 1:

from django.db import connection 
MyModel.objects.latest() 
print connection.queries[-1]['sql'] 

in này:

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" DESC LIMIT 1 

Lưu ý sắp xếp này bằng creation_date DESCLIMIT khoản. Trước đây là nhờ get_latest_by trong khi thứ hai là đóng góp của latest.

Bây giờ, trường hợp 2:

MyModel.objects.order_by('creation_date').latest() 
print connection.queries[-1]['sql'] 

in

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM 
"app_mymodel" ORDER BY "app_mymodel"."creation_date" ASC LIMIT 1 

Lưu ý rằng thứ tự đã thay đổi để creation_date ASC. Đây là kết quả của việc rõ ràng order_by. Các LIMIT được tacked trên er, sau đó lịch sự latest.

Hãy để chúng tôi cũng xem Trường hợp 3: nơi bạn chỉ định rõ ràng field_name cho objects.latest().

MyModel.objects.latest('id') 
print connection.queries[-1]['sql'] 

lãm

SELECT "app_mymodel"."id", "app_mymodel"."creation_date" FROM "app_mymodel" 
ORDER BY "app_mymodel"."id" DESC LIMIT 1 
+1

Cảm ơn bạn rất nhiều vì lời giải thích tuyệt vời của bạn! Bạn đã làm cho nó rất rõ ràng với tôi cách .latest() hoạt động và những gì tôi đã làm sai. Đặc biệt là thủ thuật SQL rất hữu ích. Điều đó chắc chắn sẽ có ích trong tương lai. – Heyl1

+1

Điều gì sẽ xảy ra nếu tôi chỉ muốn có 1 giá trị cột được chèn gần đây nhất? Giả sử: chọn "app_mymodel". "Id" FROM "app_mymodel" ORDER BY "app_mymodel". "Creation_date" ASC LIMIT 1, mã python tương đương là gì? –

7

Tôi đoán đây là một tiếng bug in Django đã được cố định sau 1.3 đã được phát hành.

0

này làm việc cho tôi

latestsetuplist = SetupTemplate.objects.order_by('-creationTime')[:10][::1] 
Các vấn đề liên quan