Переопределить URL-адреса администратора Django для конкретной модели? - PullRequest
7 голосов
/ 15 апреля 2011

Сначала немного фона:

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

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

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

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

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

Есть идеи, как переопределить URL, используемый администратором?

Ответы [ 3 ]

8 голосов
/ 15 апреля 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 сайта и добавить подстановочный или особый случай для модели 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
6 голосов
/ 15 апреля 2011

Вы можете переопределить queryset-метод вашего EventModelAdmin и отфильтровать набор запросов так, чтобы Film-Events исключались.

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

class EventAdmin(admin.ModelAdmin):

    def queryset(self, request):
        qs = super(EventAdmin, self).queryset(request)
        return qs.exclude(event_type='film')
0 голосов
/ 09 мая 2019

Вы также можете создать подкласс 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...