Переопределить URL-адреса администратора Django для конкретной модели?

Сначала немного предыстории:

У меня есть Event модель, у которой есть разные event_type. Я хочу разбить один из этих типов событий, «Фильм», на отдельного администратора. У меня есть базовая функциональность: модель прокси, унаследованная от Event, с именем Film, настраиваемый менеджер для этой модели прокси, который фильтрует ее только по типам событий «фильм», и собственный ModelAdmin.

Проблема в обратном. Теперь мне нужно отфильтровать фильмы от главного Event админа. Я не хочу изменять модель Event или ее менеджера по умолчанию, потому что влияние будет слишком большим. Итак, я попытался создать другую модель прокси, EventAdminProxy, с единственной целью - предоставить отфильтрованный список событий в админке. Затем я регистрирую эту модель вместо Event в существующем ModelAdmin.

Это, очевидно, работает, но имеет неприятный побочный эффект в виде изменения URL-адресов в админке. Вместо того, чтобы список изменений находился в «/ admin / event / event /», теперь он находится в «/ admin / event / eventadminproxy /».

Я пытаюсь сохранить эту настройку, но также сохранить старый URL-адрес. Я пробовал перегрузить метод get_urls ModelAdmin, но, насколько я могу судить, вы не можете контролировать полный URL-адрес, а только то, что идет после части "/ app_label / model_class /".

Я подумал о том, чтобы переопределить его в основном urls.py, но не могу найти приемлемого представления для привязки. Фактические представления доступны только для созданного экземпляра объекта ModelAdmin, но не для самого класса.

Любые идеи о том, как переопределить URL-адрес, используемый в админке?


person Chris Pratt    schedule 15.04.2011    source источник


Ответы (3)


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

Что-то похожее на это:

class EventAdmin(admin.ModelAdmin):

    def queryset(self, request):
        qs = super(EventAdmin, self).queryset(request)
        return qs.exclude(event_type='film')
person arie    schedule 15.04.2011
comment
В порядке. Добавьте его в категорию «Я идиот». Не могу поверить, что не подумал об этом. Спасибо! - person Chris Pratt; 15.04.2011

Если посмотреть на исходный код Django, URL-адреса администратора построены в двух местах: в экземплярах ModelAdmin и в экземплярах AdminSite.

Часть, которую вы хотите изменить, встроена в экземпляр AdminSite (django.contrib.admin.sites.AdminSite), вы можете создать подкласс и переопределить метод get_urls. Если вы посмотрите на вторую половину метода, вы увидите следующее:

    # Add in each model's views.
    for model, model_admin in self._registry.iteritems():
        urlpatterns += patterns('',
            url(r'^%s/%s/' % (model._meta.app_label, model._meta.module_name),
                include(model_admin.urls))
        )

Там он добавляет модель ._meta.module_name, которая представляет собой просто имя модели в нижнем регистре (django.db.models.options.Options.contribute_to_class).

Легкий выход - переопределить метод get_urls сайта и добавить dict или специальный случай для модели Proxy, чтобы он использовал другой URL вместо model._meta.module_name, что-то вроде строк:

класс MyAdminSite (AdminSite):

module_name_dict = {
    EventAdminProxy: 'myfunkymodulename'
}

def get_urls(self):
    base_patterns = super(MyAdminSite, self).get_urls()
    my_patterns = patterns('',)

    for model, model_admin in self._registry.iteritems():
        if model in self.module_name_dict:
            module_name = self.module_name_dict[model]
            my_patterns += patterns('',
                url(r'^%s/%s/' % (model._meta.app_label, module_name),
                    include(model_admin.urls))
            )

    return my_patterns + base_patterns
person Jj.    schedule 15.04.2011

Вы также можете создать подкласс ChangeList и переопределить метод url_for_result(), чтобы настроить URL-адреса для изменения (изучено из другого ответа), например:

from django.contrib.admin.views.main import ChangeList

class FooChangeList(ChangeList):
    def url_for_result(self, obj):
        return '/foos/foo/{obj.pk}/'

class FooAdmin(admin.ModelAdmin):
    def get_changelist(self, request, **kwargs):
        return FooChangeList

Адаптированный пример для вопроса:

from django.contrib.admin.views.main import ChangeList
from django.urls import reverse

class FilmAdmin(admin.ModelAdmin):
    def get_changelist(self, request, **kwargs):
        class FilmChangeList(ChangeList):
            def url_for_result(self, obj):
                return reverse('admin:events_event_change', args=(obj.pk, ))
        return FilmChangeList
person niekas    schedule 09.05.2019