admin管理界面的urls的生成

 

为了可以在django应用中使用admin管理界面,可以在urls.py中增加以下一些代码:

# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()

...
urlpatterns = patterns('',
    ...  
    # Uncomment the next line to enable the admin:
    (r'^admin/', include(admin.site.urls)),
    ...
)

 

 

下面来分析一下admin对应的urls是如何引用的。

首先来看autodiscover()

源码位于django\contrib\admin\__init__.py中:

def autodiscover():
    ...
    for app in settings.INSTALLED_APPS:
        mod = import_module(app)
        # Attempt to import the app's admin module.
        try:
            before_import_registry = copy.copy(site._registry)
            import_module('%s.admin' % app)
        except:
            site._registry = before_import_registry

 

这个函数将settings.INSTALLED_APPS列表中的app进行注册或导入相关模块,如admin有关的进行注册,以后可以使用site._registry来进行引用。(此处不包含model的注册)

 

真正产生urls的是(r’^admin/’, include(admin.site.urls))。

admin.site是在django\contrib\sites.py中的最后一行生成的。

site = AdminSite()

所以admin.site.urls实际上是类AdminSite的属性。

    def urls(self):
        return self.get_urls(), self.app_name, self.name
    urls = property(urls)

 

从上面的代码看生成的关键在于类AdminSite的方法get_urls()中

    def get_urls(self):
        ...
        # Admin-site-wide views.(Admin-site范围的视图)
        urlpatterns = patterns('',
            url(r'^$',
                wrap(self.index),
                name='index'),
            url(r'^logout/$',
                wrap(self.logout),
                name='logout'),
            url(r'^password_change/$',
                wrap(self.password_change, cacheable=True),
                name='password_change'),
            url(r'^password_change/done/$',
                wrap(self.password_change_done, cacheable=True),
                name='password_change_done'),
            url(r'^jsi18n/$',
                wrap(self.i18n_javascript, cacheable=True),
                name='jsi18n'),
            url(r'^r/( P<content_type_id>\d+)/( P<object_id>.+)/$',
                'django.views.defaults.shortcut'),
            url(r'^( P<app_label>\w+)/$',
                wrap(self.app_index),
                name='app_list')
        )

        # Add in each model's views.(增加每个model的视图)
        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))
            )
        return urlpatterns

 

 

对于每个model的url是通过include(model_admin.urls)来进行加入的.而每个model是使用admin.site.register(model_name,modelAdmin)等形式来注册的.下面来查看AdminSite的register函数:

    def register(self, model_or_iterable, admin_class=None, **options):
 	...
        for model in model_or_iterable:
	    ...
            if options:
                # For reasons I don't quite understand, without a __module__
                # the created class appears to "live" in the wrong place,
                # which causes issues later on.
                options['__module__'] = __name__
                admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)
	    ...
            # Instantiate the admin class to save in the registry
            self._registry[model] = admin_class(model, self)

 

可以看出get_urls()中model_admin应该是类ModelAdmin的实例.所有model_admin.urls实际上是类ModelAdmin的属性,具体的与admin-site视图的urls处理类似了.

    def get_urls(self):
        ...
        urlpatterns = patterns('',
            url(r'^$',
                wrap(self.changelist_view),
                name='%s_%s_changelist' % info),
            url(r'^add/$',
                wrap(self.add_view),
                name='%s_%s_add' % info),
            url(r'^(.+)/history/$',
                wrap(self.history_view),
                name='%s_%s_history' % info),
            url(r'^(.+)/delete/$',
                wrap(self.delete_view),
                name='%s_%s_delete' % info),
            url(r'^(.+)/$',
                wrap(self.change_view),
                name='%s_%s_change' % info),
            )
        return urlpatterns

    def urls(self):
        return self.get_urls()
    urls = property(urls)

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注