覆盖特定模型的Django管理员URL?

时间:2021-08-27 19:18:44

First a little background:

首先是一点背景:

I have an Event model that has various event_types. I want to break one of those event types, 'Film', into it's own admin. I have the basic functionality in place: a proxy model inheriting from Event, named Film, a custom manager for that proxy model that filters it to only 'film' event types, and it's own ModelAdmin.

我有一个具有各种event_types的事件模型。我想打破其中一个事件类型,'电影',进入它自己的管理员。我有基本功能:继承自Event的代理模型,名为Film,该代理模型的自定义管理器,仅将其过滤为“电影”事件类型,并且它是自己的ModelAdmin。

The problem is with the reverse. I now need to filter out films from the main Event admin. I don't want to alter the Event model or its default manager, because the impact would be too widespread. So, I tried creating another proxy model, EventAdminProxy, with the sole purpose of providing a filtered list of events in the admin. I then register this model, instead of Event, with the existing ModelAdmin.

问题是相反的。我现在需要从主要的活动管理员中过滤掉电影。我不想改变事件模型或其默认管理器,因为影响太大了。因此,我尝试创建另一个代理模型EventAdminProxy,其唯一目的是在管理员中提供过滤的事件列表。然后,我使用现有的ModelAdmin注册此模型,而不是Event。

This obviously works, but it has the unfortunate side-effect of altering the URLs in the admin. Instead of the changelist being at "/admin/event/event/", it's now at "/admin/event/eventadminproxy/".

这显然有效,但它有改变管理员URL的不幸副作用。而不是更改列表位于“/ admin / event / event /”,它现在位于“/ admin / event / eventadminproxy /”。

What I'm trying to do is keep this setup, but also keep the old URL. I've tried overloading the ModelAdmin's get_urls method, but from what I can tell, you can't control the full URL there, only what comes after the "/app_label/model_class/" part.

我要做的是保持这个设置,但也保留旧的URL。我试过重载ModelAdmin的get_urls方法,但从我所知道的,你无法控制那里的完整URL,只有“/ app_label / model_class /”之后的内容。

I thought about overriding it in the main urls.py, but can't figure out an acceptable view to tie into. The actual views are only available on the instantiated ModelAdmin object, not the class itself.

我想在主urls.py中覆盖它,但无法找出可接受的视图。实际视图仅在实例化的ModelAdmin对象上可用,而不是类本身。

Any ideas of how override the URL being used in the admin?

有关如何覆盖管理员中使用的URL的任何想法?

2 个解决方案

#1


6  

You could override the queryset-method of your EventModelAdmin and filter the queryset so that Film-Events get excluded.

您可以覆盖EventModelAdmin的queryset-method并过滤查询集,以便排除Film-Events。

Something similar to this:

与此类似的东西:

class EventAdmin(admin.ModelAdmin):

    def queryset(self, request):
        qs = super(EventAdmin, self).queryset(request)
        return qs.exclude(event_type='film')

#2


8  

Looking at the Django source, the admin URLs are built in two places, in the ModelAdmin instances, and in the AdminSite instances.

查看Django源代码,管理URL在两个位置构建,在ModelAdmin实例中和AdminSite实例中。

The part you want to change is built in the AdminSite instance (django.contrib.admin.sites.AdminSite), you can subclass that and override the get_urls method. If you look at the second half of the method you'll see this:

要更改的部分是在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))
        )

There it is adding the model's ._meta.module_name which is just the model's name lowercased (django.db.models.options.Options.contribute_to_class).

它正在添加模型的._meta.module_name,它只是模型的名称lowercased(django.db.models.options.Options.contribute_to_class)。

An easy way out is to override the Site's get_urls method and add a dict or special case for the Proxy model so it uses a different url instead of model._meta.module_name, something along the lines:

一个简单的方法是覆盖Site的get_urls方法并为Proxy模型添加一个dict或特殊情况,因此它使用不同的url而不是model._meta.module_name,其中包含以下内容:

class 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

#1


6  

You could override the queryset-method of your EventModelAdmin and filter the queryset so that Film-Events get excluded.

您可以覆盖EventModelAdmin的queryset-method并过滤查询集,以便排除Film-Events。

Something similar to this:

与此类似的东西:

class EventAdmin(admin.ModelAdmin):

    def queryset(self, request):
        qs = super(EventAdmin, self).queryset(request)
        return qs.exclude(event_type='film')

#2


8  

Looking at the Django source, the admin URLs are built in two places, in the ModelAdmin instances, and in the AdminSite instances.

查看Django源代码,管理URL在两个位置构建,在ModelAdmin实例中和AdminSite实例中。

The part you want to change is built in the AdminSite instance (django.contrib.admin.sites.AdminSite), you can subclass that and override the get_urls method. If you look at the second half of the method you'll see this:

要更改的部分是在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))
        )

There it is adding the model's ._meta.module_name which is just the model's name lowercased (django.db.models.options.Options.contribute_to_class).

它正在添加模型的._meta.module_name,它只是模型的名称lowercased(django.db.models.options.Options.contribute_to_class)。

An easy way out is to override the Site's get_urls method and add a dict or special case for the Proxy model so it uses a different url instead of model._meta.module_name, something along the lines:

一个简单的方法是覆盖Site的get_urls方法并为Proxy模型添加一个dict或特殊情况,因此它使用不同的url而不是model._meta.module_name,其中包含以下内容:

class 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