首先是一点背景:
我的Event
模型有各种event_type
个。我想打破其中一个事件类型,'电影',进入它自己的管理员。我有基本的功能:继承自Event
的代理模型,名为Film
,该代理模型的自定义管理器将其过滤为“电影”事件类型,并且它是自己的ModelAdmin。 / p>
问题在于相反。我现在需要从主Event
管理员中过滤掉电影。我不想改变Event
模型或其默认管理器,因为影响太大了。因此,我尝试创建另一个代理模型EventAdminProxy
,其唯一目的是在管理员中提供过滤的事件列表。然后,我使用现有的ModelAdmin注册此模型,而不是Event
。
这显然有效,但它在更改管理员中的URL时会产生令人遗憾的副作用。而不是更改列表位于“/ admin / event / event /”,它现在位于“/ admin / event / eventadminproxy /".
我要做的是保留此设置,但也保留旧网址。我已经尝试重载ModelAdmin的get_urls
方法,但从我所知道的,你无法控制那里的完整URL,只能在“/ app_label / model_class /”部分之后控制。
我考虑过在主urls.py中覆盖它,但无法找出可接受的视图。实际视图仅在实例化的ModelAdmin对象上可用,而不是类本身。
有关如何覆盖管理员中使用的网址的任何想法?
答案 0 :(得分:8)
查看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
方法,并为代理模型添加一个字典或特殊情况,以便它使用不同的网址而不是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
答案 1 :(得分:6)
您可以覆盖EventModelAdmin
的{{3}}并过滤查询集,以便排除电影事件。
类似的东西:
class EventAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(EventAdmin, self).queryset(request)
return qs.exclude(event_type='film')
答案 2 :(得分:0)
您还可以继承ChangeList
的子类,并覆盖url_for_result()
方法以自定义更改网址(从another answer中学习),例如:
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