Django yöneticisinde aynı model için birden fazla ModelAdmins / görünüm


150

Her biri farklı şekilde özelleştirilmiş ve farklı URL'lere bağlı olan aynı model için birden fazla ModelAdmin nasıl oluşturabilirim?

Diyelim Gönderiler adlı bir Django modelim var. Varsayılan olarak, bu modelin yönetici görünümünde tüm Post nesneleri listelenir.

List_display gibi değişkenleri ayarlayarak veya querysetbenim ModelAdmin yöntemini geçersiz kılmak gibi sayfada görüntülenen nesnelerin listesini özelleştirebilirsiniz biliyorum :

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)

Varsayılan olarak, URL'den erişilebilir /admin/myapp/post. Ancak aynı modelin birden fazla görünüm / ModelAdmins olmasını istiyorum. örneğin /admin/myapp/posttüm yayın nesnelerini /admin/myapp/mypostslisteler ve kullanıcıya ait /admin/myapp/draftposttüm yayınları listeler ve henüz yayınlanmamış tüm yayınları listeleyebilir. (bunlar sadece örnektir, gerçek kullanım durumum daha karmaşıktır)

Aynı model için birden fazla ModelAdmin kaydedemezsiniz (bu bir AlreadyRegisteredistisnayla sonuçlanır ). İdeal olarak bunu başarmak istiyorum olmadan tek ModelAdmin sınıfa şeyi koyarak ve URL'ye bağlı olarak farklı bir Sorgu Kümesi dönmek için kendi 'URL'leri' işlevini yazma.

Django kaynağına bir göz attım ve aşağıdaki gibi fonksiyonları görüyorum ModelAdmin.changelist_view şekilde benim urls.py içine dahil olabilir , ama tam olarak nasıl çalışacağından emin değilim.

Güncelleme : İstediğimi yapmanın bir yolunu buldum (aşağıya bakın), ama yine de bunu yapmanın başka yollarını duymak isterim.

Yanıtlar:


276

Her modelin yalnızca bir kez kaydedilebileceği gerçeğini ele almak için proxy modelleri kullanarak istediğimi elde etmenin bir yolunu buldum.

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)

Ardından varsayılan PostAdminadrese erişilebilir /admin/myapp/postve kullanıcının sahip olduğu yayınların listesi olur /admin/myapp/myposts.

Http://code.djangoproject.com/wiki/DynamicModels'e baktıktan sonra , aynı şeyi yapmak için aşağıdaki işlev yardımcı işlevini buldum:

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

Bu aşağıdaki gibi kullanılabilir:

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
bu harika. Ben bir proxy modeli yönetici sitesinde kayıtlı olabilir farkında değildi. bu bana çok yardımcı olacak.
Brandon Henry

8
Aynı modelleri django admin'de iki kez kaydetmem gerekiyordu ve proxy modelleri çalışıyor gibi görünüyor. Ancak izin sistemiyle ilgili bir sorun buldum. Buraya bakın: code.djangoproject.com/ticket/11154
bjunix

4
ModelAdmin sorgu kümesi yerine varsayılan yöneticiyi değiştirmek de iyi bir fikirdir. Bu nedenle proxy modelinin davranışı yönetici dışında bile tutarlıdır.
bjunix

4
Şimdi asıl cevap, django neden aynı model için iki yöneticinizin olmasına izin vermiyor? bunu kontrol eden ve hata veren 2 satır için bir şeyleri hacklememeliyiz: s. Hala harika bir cevap!
Hassek

1
@zzart: sadece eksik dokümanlar gibi görünen bekleyen bir çekme isteği var: github.com/django/django/pull/146/files
blueyed

3

Paul Stone'un cevabı kesinlikle harika! Sadece eklemek için, Django 1.4.5 için özel sınıfımı devralmak zorunda kaldımadmin.ModelAdmin

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.