2009-05-19 3 views
24

Làm thế nào để bạn xác định một thứ tự cụ thể trong Django QuerySet s?Đặt hàng tùy chỉnh ở Django

Cụ thể, nếu tôi có số QuerySet như sau: ['a10', 'a1', 'a2'].

Thứ tự thông thường (sử dụng Whatever.objects.order_by('someField')) sẽ cho tôi ['a1', 'a10', 'a2'], trong khi tôi đang tìm kiếm: ['a1', 'a2', 'a10'].

Cách thích hợp để xác định kỹ thuật đặt hàng của riêng tôi là gì?

Trả lời

39

Theo như tôi biết, không có cách nào để chỉ định thứ tự phía cơ sở dữ liệu theo cách này vì nó sẽ quá cụ thể cho phụ trợ. Bạn có thể muốn dùng đến tốt phân loại Python old-fashioned:

class Foo(models.Model): 
    name = models.CharField(max_length=128) 

Foo.objects.create(name='a10') 
Foo.objects.create(name='a1') 
Foo.objects.create(name='a2') 

ordered = sorted(Foo.objects.all(), key=lambda n: (n[0], int(n[1:]))) 
print ordered # yields a1, a2, 10 

Nếu bạn thấy mình cần loại này phân loại rất nhiều, tôi khuyên bạn nên thực hiện một phân lớp tùy chỉnh models.Manager cho mô hình của bạn mà thực hiện việc đặt hàng. Một cái gì đó như:

class FooManager(models.Manager): 
    def in_a_number_order(self, *args, **kwargs): 
     qs = self.get_query_set().filter(*args, **kwargs) 
     return sorted(qs, key=lambda n: (n[0], int(n[1:]))) 

class Foo(models.Model): 
    ... as before ... 
    objects = FooManager() 

print Foo.objects.in_a_number_order() 
print Foo.objects.in_a_number_order(id__in=[5, 4, 3]) # or any filtering expression 
+0

điểm trên! Câu trả lời tuyệt vời, cảm ơn! –

+2

Tôi gặp lỗi này khi thử phương pháp này:: \t Đối tượng 'Mô hình' không thể lập chỉ được – ninja123

+0

Có 'sắp xếp' trả về bộ truy vấn không? Cho rằng nó đã được thông qua một queryset, tôi sẽ nghĩ như vậy, nhưng tôi nghĩ rằng nó cũng có thể được chuyển đổi thành một danh sách hoặc một cái gì đó nội bộ để phân loại, sau đó * rằng * được trả lại. –

0

Tùy thuộc vào nơi bạn muốn sử dụng.

Nếu bạn muốn sử dụng nó trong mẫu của riêng mình, tôi khuyên bạn nên viết mẫu thẻ, sẽ thực hiện yêu cầu cho bạn Trong đó, bạn có thể sử dụng bất kỳ thuật toán sắp xếp nào bạn muốn sử dụng.

Trong quản trị tôi tùy chỉnh sắp xếp bằng cách mở rộng các mẫu để nhu cầu của tôi và tải một mẫu-tag như mô tả ở trên

25

@ câu trả lời Jarret của (làm các loại bằng Python) hoạt động tốt đối với trường hợp đơn giản. Ngay khi bạn có một bảng lớn và muốn, chỉ cần kéo trang đầu tiên của kết quả được sắp xếp theo một cách nhất định, phương pháp này sẽ bị ngắt (bạn phải kéo từng hàng từ cơ sở dữ liệu trước khi có thể thực hiện sắp xếp). Tại thời điểm đó tôi sẽ xem xét thêm một trường "sắp xếp" không chuẩn hóa mà bạn điền từ trường "tên" vào thời gian lưu, để bạn có thể sắp xếp theo cấp độ DB theo cách thông thường.

+2

+1 để giải quyết các vấn đề liên quan đến hiệu suất; trên thực tế, đề xuất của bạn là đề xuất chúng tôi sử dụng trên một số dữ liệu được sử dụng cho báo cáo, trong môi trường độc lập DB và chúng tôi có hàng chục triệu hàng, vì vậy tôi có thể xác minh rằng nó hoạt động tốt . –

0

Nếu bạn có bộ dữ liệu lớn hơn và sử dụng thêm một backend Solr (ví dụ: với Haystack):

Sử dụng solr.ICUCollationField với các tùy chọn numeric=true as type cho các lĩnh vực phân loại. Điều này sẽ sắp xếp theo ngôn ngữ và nếu số có mặt sẽ sắp xếp phần số theo quy tắc số thay vì sắp xếp chuỗi.

Xem: https://cwiki.apache.org/confluence/display/solr/Language+Analysis#LanguageAnalysis-UnicodeCollation http://www.solr-start.com/javadoc/solr-lucene/org/apache/solr/schema/ICUCollationField.html