1、总体看Admin执行流程 1. 启动adminjavascript
首先须要将django.contrib.admin添加到INSTALL_APP中 当加载django中app的时候,执行每个app下的admin.py 2. 注册模型 每一个模型均可以指定一个ModelAdmin 封装了该模型特定的管理功能 实例化一个AdminSite,并告诉它模型类和ModelAmin admin.site --> 实例化一个AdminSite admin.site.register(Book) 注册Book表 3. 设计URL并将AdminSite实例挂钩到您的URLconfig中 url(r'admin/',admin.site.urls)
2、admin.site.registerjava
django启动的时候,顺序为:先register,而后urls分配 先看看admin.siter.register作了什么
[Python] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40django
class AdminSite(object): .... def __init__(self, name='admin'): self._registry = {} # AdminSite初始化函数定义了一个字典 self.name = name self._actions = {'delete_selected': actions.delete_selected} self._global_actions = self._actions.copy() all_sites.add(self) def register(self, model_or_iterable, admin_class=None, **options): # 判断是否自定义了ModelAdmin if not admin_class: admin_class = ModelAdmin if isinstance(model_or_iterable, ModelBase): model_or_iterable = [model_or_iterable] for model in model_or_iterable: if model._meta.abstract: raise ImproperlyConfigured( 'The model %s is abstract, so it cannot be registered with admin.' % model.__name__ ) if model in self._registry: raise AlreadyRegistered('The model %s is already registered' % model.__name__) if not model._meta.swapped: 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) # 以传入的model类做为字典的key,ModelAdmin做为字典value self._registry[model] = admin_class(model, self) 总结:
就是实例化了一个AdminSite类,admin.site 采用的是模板的单例模式app
在AdminSite中定义了一个字典 字典的key是模型类,value是ModelAdmin
3、admin.site.urlside
[Python] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40函数
@property def urls(self): return self.get_urls(), 'admin', self.name def get_urls(self): from django.conf.urls import url, include from django.contrib.contenttypes import views as contenttype_views def wrap(view, cacheable=False): ..... return update_wrapper(wrapper, view) # Admin-site-wide views. urlpatterns = [ url(r'^$', wrap(self.index), name='index'), url(r'^login/$', self.login, name='login'), 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>.+)/$', wrap(contenttype_views.shortcut), name='view_on_site'), ] valid_app_labels = [] # 模型类,ModelAdmin self._registry字典 for model, model_admin in self._registry.items(): urlpatterns += [ # url(r'^%s/%s/' % (模型所在的app名, 模型名), include(每一个模型对应的ModelAdmin中urls)), url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)), ] if model._meta.app_label not in valid_app_labels: valid_app_labels.append(model._meta.app_label) ..... #返回了n个URL return urlpatterns 首先urls是一个函数,被装饰为属性,urls返回一个元组,元组的第一个参数是列表,由get_urls()返回。 在get_urls()中定义了一个urlpatterns,并最终返回,urlpatterns里面存放的是url匹配规则和对应的视图函数。 当用户在admin中注册模型类的时候:
[Python] 纯文本查看 复制代码
?
1
admin.site.register(models.UserInfo) # 注册的时候没有传入admin_class,默认使用的是ModelAdmin ui
会根据下面的代码添加到urlpatterns中
[Python] 纯文本查看 复制代码
?
1
2
3
4
for model, model_admin in self._registry.items():url
urlpatterns += [ url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)), ] model._meta.app_label: 是model类存在的app名,就是UserInfo存在哪一个app中 model._mate.model_name:是模型类的类名,小写。这里是userinfo。 这样就生成了/app01/userinfo/ 这样的url前缀。 include(model_admin.urls):包含模型类对应ModelAdmin中urls。这里没有指定ModelAdmin,因此使用官方默认的ModelAdmin
[size=1.375em]设计
4、ModelAdmin.urls
[Python] 纯文本查看 复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def get_urls(self):code
from django.conf.urls import url def wrap(view): def wrapper(*args, **kwargs): return self.admin_site.admin_view(view)(*args, **kwargs) wrapper.model_admin = self return update_wrapper(wrapper, view) info = self.model._meta.app_label, self.model._meta.model_name urlpatterns = [ 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'^(.+)/change/$', wrap(self.change_view), name='%s_%s_change' % info), # For backwards compatibility (was the change url before 1.9) url(r'^(.+)/$', wrap(RedirectView.as_view( pattern_name='%s:%s_%s_change' % ((self.admin_site.name,) + info) ))), ] return urlpatterns @property def urls(self): return self.get_urls() 在ModelAdmin中urls()也是一个函数,被装饰器装饰为属性。get_urls()返回一个urlpatterns. 红色部分的urlpatterns 代表了django admin为何注册了一个类以后就为这个类提供了基本的增删改查等基本的url和映射了。
[size=1.5em]
[size=1.5em]5、最终的url
[Python] 纯文本查看 复制代码?1url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),