2012-09-10 12 views
46

Một trong những mô hình của tôi có một lá cờ xóa, được sử dụng để ẩn các đối tượng trên toàn cầu:Override queryset mặc định trong Django quản trị

class NondeletedManager(models.Manager): 
    """Returns only objects which haven't been deleted""" 

    def get_query_set(self): 
     return super(NondeletedManager, self).get_query_set().exclude(deleted=True) 

class Conversation(BaseModel): 
    ... 
    deleted = models.BooleanField(default=False) 
    objects = NondeletedManager() 
    all_conversations = models.Manager() # includes deleted conversations 

Làm thế nào tôi có thể ghi đè lên các queryset mặc định được sử dụng bởi mô-đun quản trị Django để bao gồm cuộc hội thoại đã bị xóa?

+0

Bạn có thực sự cần người quản lý tùy chỉnh cho các truy vấn đơn giản đó không? –

+2

Có, các đối tượng đã xóa sẽ bị bỏ qua phổ biến (ngoại trừ trên các trang quản trị), do đó, bạn nên đặt mặc định. –

Trả lời

86

Bạn có thể overrideget_queryset phương pháp trong lớp quản trị mô hình của mình.

class MyModelAdmin(admin.ModelAdmin): 
    def get_queryset(self, request): 
     qs = super(MyModelAdmin, self).get_queryset(request) 
     if request.user.is_superuser: 
      return qs 
     return qs.filter(author=request.user) 

Lưu ý trong Django < = 1,5 phương thức được đặt tên chỉ queryset.

+2

Làm thế nào mà sẽ làm việc trong trường hợp này? Tôi có thể sửa đổi queryset được tạo bởi 'ModelAdmin.queryset' để bao gồm các đối tượng đã xóa không? Tôi không muốn tự xây dựng queryset thay vì gọi superclass. –

+0

Nhìn vào câu trả lời của tôi để xem ý tôi là gì. Có cách nào khác để hoàn toàn thực hiện lại chức năng này không? –

+3

Nó giúp thực sự đặt câu trả lời trong câu trả lời của bạn, thay vì chỉ liên kết. Liên kết đó đã chết, vì vậy tôi sẽ cập nhật để giải thích. – Dan

2

Điều gì sẽ là rất sai trái với những điều sau đây:

class Conversation(BaseModel): 
    ... 
    deleted = models.BooleanField(default=False) 
    objects = models.Manager() # includes deleted conversations 
    nondeleted_conversations = NondeletedManager() 

Vì vậy, trong ứng dụng của riêng/dự án của bạn, bạn sử dụng Conversation.nondeleted_conversations() và để tích hợp trong ứng dụng quản trị làm điều đó là điều.

+1

Tôi bỏ qua các đối tượng đã xóa ở mọi nơi * nhưng * các trang quản trị, vì vậy tôi nghĩ rằng đó nên là mặc định. Hơn nữa, theo cách này, tôi không cần phải cập nhật mã cũ bằng cách thêm khả năng xóa cuộc trò chuyện. –

7

Konrad là chính xác, nhưng điều này khó hơn ví dụ được đưa ra trong tài liệu.

Cuộc hội thoại đã xóa không thể được bao gồm trong bộ truy vấn đã loại trừ chúng. Vì vậy, tôi không thấy một tùy chọn nào khác ngoài việc triển khai lại admin.ModelAdmin.queryset hoàn toàn.

class ConversationAdmin (admin.ModelAdmin): 

    def queryset (self, request): 
     qs = Conversation.all_conversations 
     ordering = self.get_ordering(request) 
     if ordering: 
      qs = qs.order_by(*ordering) 
     return qs 
+0

Tôi không nghĩ có bất cứ điều gì sai trái với điều đó. Sử dụng hai người quản lý là con đường để đi. Đó là sự thật, tuy nhiên, rằng các admin Django có thể cung cấp một cái móc để bạn không phải thực hiện lại phần đặt hàng. –

1

Giải pháp được chấp nhận phù hợp với tôi nhưng tôi cần linh hoạt hơn một chút, vì vậy tôi đã mở rộng chế độ xem danh sách thay đổi để thêm vào tham số truy vấn tùy chỉnh. Bây giờ tôi có thể định cấu hình bộ truy vấn/bộ lọc mặc định của mình và nó vẫn có thể được sửa đổi bằng cách sử dụng một bộ lọc khác (nhận tham số):

def changelist_view(self, request, extra_context=None): 
    if len(request.GET) == 0 : 
     q = request.GET.copy() 
     q['status__gt'] = 4 
     request.GET = q 
     request.META['QUERY_STRING'] = request.GET.urlencode() 

    return super(WorksheetAdmin,self).changelist_view(request, extra_context=extra_context)