Override Django Admin URLs for Specific Model?

后端 未结 3 1405
一生所求
一生所求 2021-02-15 20:30

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 o

相关标签:
3条回答
  • 2021-02-15 21:05

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

    Something similar to this:

    class EventAdmin(admin.ModelAdmin):
    
        def queryset(self, request):
            qs = super(EventAdmin, self).queryset(request)
            return qs.exclude(event_type='film')
    
    0 讨论(0)
  • 2021-02-15 21:05

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

    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:

        # 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).

    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:

    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
    
    0 讨论(0)
  • 2021-02-15 21:15

    You could also subclass ChangeList and override the url_for_result() method to customise change urls, (learned from another answer), e.g.:

    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
    

    Adapted example for the question:

    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
    
    0 讨论(0)
提交回复
热议问题