Несколько ModelAdmins / представлений для одной и той же модели в админке Django - PullRequest
141 голосов
/ 08 февраля 2010

Как я могу создать более одного ModelAdmin для одной и той же модели, каждый из которых настроен по-разному и связан с разными URL-адресами?

Допустим, у меня есть модель Django, которая называется Posts. По умолчанию в административном представлении этой модели перечислены все объекты Post.

Я знаю, что могу настроить список объектов, отображаемых на странице, различными способами, установив переменные, такие как 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)

По умолчанию это будет доступно по URL /admin/myapp/post. Однако я хотел бы иметь несколько представлений / ModelAdmins одной и той же модели. например, /admin/myapp/post будет перечислять все объекты постов, а /admin/myapp/myposts будет перечислять все посты, принадлежащие пользователю, а /admin/myapp/draftpost может перечислять все посты, которые еще не были опубликованы. (это всего лишь примеры, мой фактический вариант использования более сложный)

Вы не можете зарегистрировать более одного ModelAdmin для одной и той же модели (это приводит к исключению AlreadyRegistered). В идеале я хотел бы добиться этого без , помещая все в один класс ModelAdmin и писать свою собственную функцию 'urls', чтобы возвращать другой набор запросов в зависимости от URL.

Я посмотрел на источник Django и вижу такие функции, как ModelAdmin.changelist_view, которые могут быть каким-то образом включены в мой urls.py, но я не уверен, как именно это будет работать.

Обновление : я нашел один способ сделать то, что я хочу (см. Ниже), но я все еще хотел бы услышать другие способы сделать это.

Ответы [ 2 ]

250 голосов
/ 09 февраля 2010

Я нашел один способ добиться того, чего я хочу, используя прокси-модели, чтобы обойти тот факт, что каждая модель может быть зарегистрирована только один раз.

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

class MyPosts(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)
3 голосов
/ 11 сентября 2013

Пол Стоун отвечает просто великолепно! Чтобы добавить, для Django 1.4.5 мне нужно было унаследовать мой пользовательский класс от admin.ModelAdmin

class MyPostAdmin(admin.ModelAdmin):
    def queryset(self, request):
        return self.model.objects.filter(id=1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...