Подтвердить что ты не робот

Django - расширение других приложений ModelAdmin?

Есть ли способ расширить другие приложения ModelAdmin?

У меня есть проект, который использует функции, предлагаемые django.contrib.comments.

Класс CommentAdmin ModelAdmin:
actions = ["flag_comments", "approve_comments", "remove_comments"]

Я хотел бы добавить комментарийAdmin ModelAdmin в свой проект, чтобы включить действие ban_user.

Я попытался создать свой собственный объект NewCommentsAdmin(CommentsAdmin) в моем файле admin.py и зарегистрировать его, но я получаю уведомление 'AlreadyRegistered at /admin/' 'The model Comment is already registered'.

class NewCommentAdmin(CommentAdmin):
    actions = ['ban_user']

    def ban_user(self, request, queryset):
        pass

admin.site.register(Comment, NewCommentAdmin)

Есть ли способ сделать это без изменения исходного кода django.contrib.comments?

4b9b3361

Ответ 1

Я думаю, у вас есть что-то вроде этого в верхней части вашего файла:

from django.contrib.comments.admin import CommentAdmin

Этот импорт выполняет регистрацию модели (в самом низу этого файла администратора) снова.

Одна идея, которая выглядит не очень красиво (на самом деле я ее не пробовал):

from django.contrib.comments.models import Comment
from django.contrib import admin
from django.contrib.admin.sites import NotRegistered

# Try to unregister the Comment model 
# that was registered via the auto_discover method
try:
    admin.site.unregister(Comment)
except NotRegistered:
    pass

# Now we can load the CommentAdmin (which reregisters the admin model)
from django.contrib.comments.admin import CommentAdmin

# We have to unregister again:
try:
    admin.site.unregister(Comment)
except NotRegistered:
    pass

# Now your stuff...

Я думаю, это можно было бы сделать лучше, но это должно сработать. Чтобы этот подход работал, приложение, содержащее этот файл, должно быть после приложения комментариев в INSTALLED_APPS.

Теперь к вашему классу. Я думаю, что если вы пишете actions = ['ban_user'], вы фактически перезаписываете все действия в родительском классе. Я думаю, что это самый простой способ переопределить метод get_actions:

class NewCommentAdmin(CommentAdmin):

    def get_actions(self, request):
        actions = super(NewCommentAdmin, self).get_actions(request)

        # Do some logic here based on request.user if you want 
        # to restrict the new action to certain users
        actions.append('ban_user')

        return actions

    def ban_user(self, request, queryset):
        pass

admin.site.register(Comment, NewCommentAdmin)

Надеюсь, что это поможет (или, по крайней мере, дает представление):)

Ответ 2

Вот как я делаю это в одном проекте для модели User. В admin.py для моего приложения:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

class MyUserAdmin(UserAdmin):
    # ...

admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)

Ответ 4

Посмотрите https://github.com/kux/django-admin-extend

Он предлагает несколько простых в использовании функций и декораторов, которые реализуют функциональные возможности, которые вы запрашиваете очень гибким образом. В документации достаточно хорошо объясняется, почему использование этого подхода лучше, чем прямое наследование.

Он также поддерживает впрыскивание двунаправленных множеств во многие поля.