2010-08-16 23 views
41

Giả sử tôi có một mô hình Sách chứa khóa ngoài cho mô hình Nhà xuất bản.Làm cách nào để thêm cột đếm có thể sắp xếp vào quản trị viên Django của mô hình có quan hệ nhiều-một?

Làm cách nào tôi có thể hiển thị trong quản trị viên Django một cột với số lượng sách được xuất bản bởi mỗi nhà xuất bản, theo cách mà tôi có thể sử dụng tính năng sắp xếp được tích hợp sẵn?

Trả lời

66

Tôi gặp vấn đề tương tự (Tôi không thể thay đổi người quản lý của mô hình để thêm chú thích hoặc tham gia chậm). Một sự kết hợp của hai câu trả lời ở đây hoạt động. @Andre thực sự là gần gũi, quản trị Django hỗ trợ sửa đổi queryset cho chỉ là admin, vì vậy áp dụng cùng một logic ở đây và sau đó sử dụng thuộc tính admin_order_field. Bạn vẫn cần thêm trường quản trị mới vào list_display, tất nhiên.

from django.db.models import Count 

class EventAdmin(admin.ModelAdmin) 
    list_display = (..., 'show_artist_count') 

    def queryset(self, request): 
    # def get_queryset(self, request): for Django 1.6+ 
     qs = super(EventAdmin, self).queryset(request) 
     return qs.annotate(artist_count=Count('artists')) 

    def show_artist_count(self, inst): 
     return inst.artist_count 
    show_artist_count.admin_order_field = 'artist_count' 
+2

Có cách nào để đặt cài đặt này làm phương thức đặt hàng mặc định không? ví dụ = ('artist_count'). Không cho tôi với trường không tồn tại. –

+4

đừng quên thêm dòng này: từ nhập django.db.models Số – Ali

+0

Cách đơn giản và gọn gàng nhất IMO nếu bạn chỉ cần đặt hàng cho trang quản trị (như OP đã nêu). Không cần phải thay đổi Trình quản lý mô hình sự kiện khi chỉ cần thay đổi quản trị viên – Patrick

0

Hãy thử một cái gì đó như thế này:

class PublisherAdminWithCount(Admin): 

    def book_count(self, obj): 
     return obj.book_set.count() 

    list_display = ('user_count',) 

admin.site.register(Group, PublisherAdminWithCount) 
+2

Rất tiếc, cột đó sẽ không thể sắp xếp được. –

7

Hãy thử điều này:

làm mới Manager (và aggregate với số lượng trên các lĩnh vực liên quan book):

class PublisherManager(models.Manager): 
    def get_query_set(self): 
     return super(PublisherManager,self).get_query_set().annotate(pubcount=Count('book')) 

sắp xếp nó vào pubcount :

class Publisher(models.Model): 
    ...... 
    objects = PublisherManager() 

    class Meta: 
     ordering = ('pubcount',) 
+1

Oooh - đó là thủ thuật khá gọn gàng, nhưng lưu ý rằng nó sẽ thêm chú thích vào mọi thứ bạn tìm kiếm bằng cách sử dụng trình quản lý đối tượng mở rộng đó. Nếu đó là một vấn đề, bạn luôn có thể tạo một trình quản lý tiêu chuẩn thứ hai mà không có tổng hợp và đính kèm nó như là 'standard_objects'. Nhưng điều đó làm tăng độ phức tạp, obv –

+2

@stevejalim, đúng vậy. Nếu bộ đếm không phải là "hoạt động", bạn cũng có thể có trường book_count trên nhà xuất bản và cập nhật nó bằng tín hiệu, bất cứ khi nào sách được lưu ..... –

+0

khi tôi thử, tôi sẽ nhận được lỗi: "đặt hàng" đề cập đến "pubcount", một trường không tồn tại. –

1

Bạn thực sự nên bắt đầu với việc thêm:

class PublisherManager(models.Manager): 
    def get_query_set(self): 
     return super(PublisherManager,self).get_query_set().annotate(pubcount=Count('book')) 

Nhưng cách chính xác để thêm nó như là một lĩnh vực có thể phân loại là:

class Publisher(models.Model): 
    ...... 
    objects = PublisherManager() 

    def count(self): 
     return self.pubcount 
    count.admin_order_field = 'pubcount' 

Và sau đó bạn chỉ có thể thêm 'đếm' đến list_display thuộc tính của quản trị viên mô hình trong admin.py

0

Câu trả lời của Lincoln B là cách phù hợp với tôi.

Lúc đầu, tôi muốn chỉ bình luận về giải pháp của mình, nhưng tôi thực sự thấy mình giải quyết một vấn đề hơi khác. Tôi đã có một lớp quản trị, mà tôi muốn "tùy chỉnh" theo nhu cầu của tôi - cụ thể là quản trị viên django-taggit. Trong một trong những ứng dụng của tôi admin.py, tôi nói thêm:

# sort tags by name in admin (count items also possible) 
from taggit.admin import TagAdmin 
TagAdmin.ordering = ["name"] 
# make sortable on item_count: 
# 1. function for lookup 
def item_count(obj): 
    """This takes the item_count from object: didn't work as model field.""" 
    return obj.item_count # not needed: obj.taggit_taggeditem_items.count() 
# 2. property in function - admin field name 
item_count.admin_order_field = 'item_count' 
# 3. queryset override, with count annotation 
from django.db.models import Count 
TagAdmin.queryset = lambda self, request: super(TagAdmin, self).queryset(request).annotate(item_count=Count('taggit_taggeditem_items')) 
# 4. add to list display 
TagAdmin.list_display = ["name", item_count] 

Các quan sát thú vị đối với tôi là, tôi có thể không chỉ chú thích các queryset, và thêm "item_count"-list_display - bởi vì không có phương pháp item_count trong TagAdmin, cũng không phải một phương thức hoặc trường trong lớp mô hình Tag (chỉ trong số queryset).

Các vấn đề liên quan