ผู้ดูแลระบบหลายรุ่น / มุมมองสำหรับรุ่นเดียวกันในผู้ดูแลระบบ Django


150

ฉันจะสร้างมากกว่าหนึ่ง ModelAdmin สำหรับรุ่นเดียวกันโดยแต่ละแบบกำหนดเองแตกต่างกันและเชื่อมโยงกับ URL ที่แตกต่างกันอย่างไร

สมมติว่าฉันมีรุ่น Django ชื่อกระทู้ ตามค่าเริ่มต้นมุมมองผู้ดูแลระบบของรุ่นนี้จะแสดงรายการวัตถุโพสต์ทั้งหมด

ฉันรู้ว่าฉันสามารถปรับแต่งรายการของวัตถุที่แสดงบนหน้าในรูปแบบต่างๆโดยการตั้งค่าตัวแปรเช่น list_display หรือแทนที่querysetวิธีการใน ModelAdmin ของฉันเช่น:

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)

โดยค่าเริ่มต้นนี้จะสามารถเข้าถึงได้ที่ /admin/myapp/postURL อย่างไรก็ตามฉันต้องการมีหลายมุมมอง / ModelAdmins ของโมเดลเดียวกัน เช่น/admin/myapp/postจะแสดงรายการออบเจกต์ทั้งหมดและ/admin/myapp/mypostsจะแสดงรายการโพสต์ทั้งหมดที่เป็นของผู้ใช้และ/admin/myapp/draftpostอาจแสดงรายการโพสต์ทั้งหมดที่ยังไม่ได้เผยแพร่ (นี่เป็นเพียงตัวอย่างกรณีการใช้จริงของฉันซับซ้อนกว่า)

คุณไม่สามารถลงทะเบียนมากกว่าหนึ่ง ModelAdmin สำหรับรุ่นเดียวกัน (ผลลัพธ์นี้มีAlreadyRegisteredข้อยกเว้น) เป็นการดีที่ฉันจะทำสิ่งนี้ให้สำเร็จโดยไม่ต้องใส่ทุกอย่างไว้ใน ClassAdmin ชั้นเดียวและเขียนฟังก์ชั่น 'urls' ของตัวเองเพื่อส่งคืนชุดสืบค้นที่แตกต่างกันขึ้นอยู่กับ URL

ฉันเคยดูที่ Django แล้วและฉันเห็นฟังก์ชั่นอย่างModelAdmin.changelist_viewนั้นอาจรวมอยู่ใน urls.py ของฉัน แต่ฉันไม่แน่ใจว่ามันจะทำงานอย่างไร

อัปเดต : ฉันพบวิธีหนึ่งในการทำสิ่งที่ฉันต้องการ (ดูด้านล่าง) แต่ฉันยังอยากได้ยินวิธีการอื่นในการทำเช่นนี้

คำตอบ:


275

ฉันพบวิธีหนึ่งในการบรรลุสิ่งที่ฉันต้องการโดยใช้แบบจำลองพร็อกซีเพื่อรับทราบข้อเท็จจริงว่าแต่ละรุ่นอาจลงทะเบียนเพียงครั้งเดียว

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)

จากนั้นเริ่มต้นPostAdminจะสามารถเข้าถึงได้และรายชื่อของโพสต์ที่เป็นเจ้าของโดยผู้ใช้จะอยู่ที่/admin/myapp/post/admin/myapp/myposts

หลังจากดูที่http://code.djangoproject.com/wiki/DynamicModelsฉันได้สร้างฟังก์ชันยูทิลิตี้ฟังก์ชั่นต่อไปนี้ขึ้นมาเพื่อทำสิ่งเดียวกัน:

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

สามารถใช้งานได้ดังนี้:

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
นี่มันเจ๋งมาก. ฉันไม่ทราบว่ารูปแบบพร็อกซีสามารถลงทะเบียนในไซต์การดูแลระบบได้ มันจะช่วยฉันได้มากจริงๆ
แบรนดอนเฮนรี่

8
ฉันต้องลงทะเบียนรุ่นเดียวกันสองครั้งในผู้ดูแลระบบ django และรุ่นพร็อกซีดูเหมือนจะทำงานได้ แต่ฉันพบปัญหาหนึ่งกับระบบการอนุญาต ดูที่นี่: code.djangoproject.com/ticket/11154
bjunix

4
มันเป็นความคิดที่ดีในการเปลี่ยนเครื่องมือจัดการเริ่มต้นแทนชุดแบบสอบถาม ModelAdmin ดังนั้นพฤติกรรมของรูปแบบพร็อกซีจึงสอดคล้องกันแม้อยู่นอกผู้ดูแลระบบ
bjunix

4
ตอนนี้คำตอบที่แท้จริงคือทำไม django ไม่ให้คุณมีผู้ดูแลสองคนสำหรับรุ่นเดียวกัน เราไม่จำเป็นต้องแฮ็กสิ่งต่าง ๆ เพียงแค่ 2 บรรทัดที่ตรวจสอบและโยนข้อผิดพลาด: s คำตอบที่ดียัง!
Hassek

1
@zzart: มีคำขอดึงที่รอดำเนินการซึ่งดูเหมือนจะเป็นเอกสารที่หายไป: github.com/django/django/pull/146/files
blueyed

3

คำตอบของ Paul Stone นั้นยอดเยี่ยมมาก! เพื่อเพิ่มสำหรับ Django 1.4.5 ฉันต้องการสืบทอดคลาสที่กำหนดเองของฉันจากadmin.ModelAdmin

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.