Nhiều ModelAdmins / lượt xem cho cùng một mô hình trong quản trị viên Django


149

Làm cách nào tôi có thể tạo nhiều ModelAdmin cho cùng một mô hình, mỗi mô hình được tùy chỉnh khác nhau và được liên kết với các URL khác nhau?

Hãy nói rằng tôi có một mô hình Django được gọi là Bài viết. Theo mặc định, chế độ xem quản trị của mô hình này sẽ liệt kê tất cả các đối tượng Đăng.

Tôi biết tôi có thể tùy chỉnh danh sách các đối tượng được hiển thị trên trang theo nhiều cách khác nhau bằng cách đặt các biến như list_display hoặc ghi đè querysetphương thức trong ModelAdmin của tôi như vậy:

class MyPostAdmin(admin.ModelAdmin):
    list_display = ('title', 'pub_date')

    def queryset(self, request):
        request_user = request.user
        return Post.objects.filter(author=request_user)

admin.site.register(MyPostAdmin, Post)

Theo mặc định, điều này sẽ có thể truy cập tại URL /admin/myapp/post. Tuy nhiên, tôi muốn có nhiều lượt xem / ModelAdmins của cùng một mô hình. ví dụ: /admin/myapp/postsẽ liệt kê tất cả các đối tượng bài đăng và /admin/myapp/mypostssẽ liệt kê tất cả các bài đăng thuộc về người dùng và /admin/myapp/draftpostcó thể liệt kê tất cả các bài đăng chưa được xuất bản. (đây chỉ là ví dụ, trường hợp sử dụng thực tế của tôi phức tạp hơn)

Bạn không thể đăng ký nhiều ModelAdmin cho cùng một mô hình (điều này dẫn đến một AlreadyRegisteredngoại lệ). Lý tưởng nhất là tôi muốn đạt được điều này mà không cần đặt mọi thứ vào một lớp ModelAdmin duy nhất và viết hàm 'url' của riêng tôi để trả về một bộ truy vấn khác tùy thuộc vào URL.

Tôi đã xem qua nguồn Django và tôi thấy các chức năng như thế ModelAdmin.changelist_viewcó thể được bao gồm trong urls.py của tôi, nhưng tôi không chắc chính xác nó sẽ hoạt động như thế nào.

Cập nhật : Tôi đã tìm thấy một cách để làm những gì tôi muốn (xem bên dưới), nhưng tôi vẫn muốn nghe những cách khác để làm điều này.

Câu trả lời:


274

Tôi đã tìm thấy một cách để đạt được những gì tôi muốn, bằng cách sử dụng các mô hình proxy để giải quyết thực tế rằng mỗi mô hình chỉ có thể được đăng ký một lần.

class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'pubdate','user')

class MyPost(Post):
    class Meta:
        proxy = True

class MyPostAdmin(PostAdmin):
    def get_queryset(self, request):
        return self.model.objects.filter(user = request.user)


admin.site.register(Post, PostAdmin)
admin.site.register(MyPost, MyPostAdmin)

Sau đó, mặc định PostAdminsẽ có thể truy cập tại /admin/myapp/postvà danh sách các bài đăng thuộc sở hữu của người dùng sẽ có tại /admin/myapp/myposts.

Sau khi xem http://code.djangoproject.com/wiki/DAVEModels , tôi đã đưa ra chức năng tiện ích chức năng sau để thực hiện điều tương tự:

def create_modeladmin(modeladmin, model, name = None):
    class  Meta:
        proxy = True
        app_label = model._meta.app_label

    attrs = {'__module__': '', 'Meta': Meta}

    newmodel = type(name, (model,), attrs)

    admin.site.register(newmodel, modeladmin)
    return modeladmin

Điều này có thể được sử dụng như sau:

class MyPostAdmin(PostAdmin):
    def get_queryset(self, request):
        return self.model.objects.filter(user = request.user)

create_modeladmin(MyPostAdmin, name='my-posts', model=Post)

8
điều này thật tuyệt. Tôi không biết rằng một mô hình proxy có thể được đăng ký trong trang quản trị. Điều này thực sự sẽ giúp tôi rất nhiều.
Brandon Henry

8
Tôi cũng cần phải đăng ký các mô hình tương tự hai lần trong quản trị django và các mô hình proxy dường như hoạt động. Nhưng tôi đã tìm thấy một vấn đề với hệ thống cấp phép. Xem tại đây: code.djangoproject.com/ticket/11154
bjunix

4
Bạn cũng nên thay đổi trình quản lý mặc định thay vì bộ truy vấn ModelAdmin. Vì vậy, hành vi của mô hình proxy là nhất quán ngay cả bên ngoài quản trị viên.
bjunix

4
Bây giờ câu trả lời thực sự là, tại sao django không cho phép bạn có hai quản trị viên cho cùng một mô hình? chúng ta không cần phải hack xung quanh mọi thứ chỉ trong 2 dòng để kiểm tra và đưa ra lỗi: s. Câu trả lời tuyệt vời vẫn còn!
Hassek

1
@zzart: có một yêu cầu kéo đang chờ xử lý, dường như chỉ thiếu các tài liệu: github.com/django/django/pull/146/files
blueyed

3

Paul Stone trả lời là hoàn toàn tuyệt vời! Chỉ cần thêm, đối với Django 1.4.5 tôi cần kế thừa lớp tùy chỉnh của mình từadmin.ModelAdmin

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.