from django.db import models class Role(models.Model): caption = models.CharField(max_length=32) class Meta: verbose_name_plural = "角色表" def __str__(self): return self.caption class UserType(models.Model): title = models.CharField(max_length=32) roles = models.ManyToManyField(to=Role) def __str__(self): return self.title class UserInfo(models.Model): name = models.CharField(max_length=32) email = models.EmailField(max_length=32) ut = models.ForeignKey(to=UserType,null=True,blank=True)
from django.db import models class Article(models.Model): title = models.CharField(max_length=32)
admin源码流程
- 文件加载
第一次导入后,再次导入时不再重新加载
a. 运行程序,找到每一个app中的 admin.py 文件,并加载
- app01.admin.py
from django.contrib import admin from app01 import models """ _registry = { models.Role: ModelAdmin(models.Role,admin.site), models.UserInfo: ModelAdmin(models.UserInfo,admin.site) models.UserType: ModelAdmin(models.UserType,admin.site) } """ admin.site.register(models.Role) admin.site.register(models.UserInfo) admin.site.register(models.UserType)
- 创建admin.site中的对象
class AdminSite中
site = AdminSite()
def __init__(self, name='admin'): self._registry = {} # model_class class -> admin_class instance self.name = name self._actions = {'delete_selected': actions.delete_selected} self._global_actions = self._actions.copy() all_sites.add(self)
- 执行对象的 register方法,目的:讲注册类添加到 _registry中
#model_or_iterable 就是我们操作的对象比如models.userinfo
#admin_class 一般是指ModelAdmin
def register(self, model_or_iterable, admin_class=None, **options): """ Registers the given model(s) with the given admin class. The model(s) should be Model classes, not instances. If an admin class isn't given, it will use ModelAdmin (the default admin options). If keyword arguments are given -- e.g., list_display -- they'll be applied as options to the admin class. If a model is already registered, this will raise AlreadyRegistered. If a model is abstract, this will raise ImproperlyConfigured. """ 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__) # Ignore the registration if the model has been # swapped out. if not model._meta.swapped: # If we got **options then dynamically construct a subclass of # admin_class with those **options. 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)
_registry 中现在存的值
_registry = {
models.Role: ModelAdmin(models.Role,admin.site),
models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
models.UserType: ModelAdmin(models.UserType,admin.site)
}
- app02.admin.py
- 用app01.admin中创建那个admin.site对象
- 执行对象的 register方法,目的:讲注册类添加到 _registry中
流程和app01一样,这里不再赘述
_registry = {
models.Role: ModelAdmin(models.Role,admin.site),
models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
models.UserType: ModelAdmin(models.UserType,admin.site)
models.Article: ModelAdmin(models.Article,admin.site)
}
admin.site是一个对象(单例模式创建),其中封装了: _registry = { models.Role: ModelAdmin(models.Role,admin.site), models.UserInfo: ModelAdmin(models.UserInfo,admin.site) models.UserType: ModelAdmin(models.UserType,admin.site) models.Article: ModelAdmin(models.Article,admin.site) }
b. urls.py
再次调用 admin.site 对象的 urls属性:
urlpatterns = [ url(r'^admin/', admin.site.urls), ]
class AdminSite中
@property def urls(self): return self.get_urls(), 'admin', self.name #返回的是一个元祖,并且第一个元素是一个列表
def get_urls(self): from django.conf.urls import url, include # Since this module gets imported in the application's root package, # it cannot import models from other applications at the module level, # and django.contrib.contenttypes.views imports ContentType. from django.contrib.contenttypes import views as contenttype_views def wrap(view, cacheable=False): def wrapper(*args, **kwargs): return self.admin_view(view, cacheable)(*args, **kwargs) wrapper.admin_site = self 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'), ] # Add in each model's views, and create a list of valid URLS for the # app_index
#model._meta.app_label 得到app的名称
# model._meta.model_name 得到当前类的名称
valid_app_labels = [] for model, model_admin in self._registry.items(): urlpatterns += [ 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) # If there were ModelAdmins registered, we should have a list of app # labels for which we need to allow access to the app_index view, if valid_app_labels: regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$' urlpatterns += [ url(regex, wrap(self.app_index), name='app_list'), ] return urlpatterns
modelAdmin中
@property def urls(self): return self.get_urls()
def get_urls(self): 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
基于admin源码简单示例
"""s6day102 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from django.shortcuts import HttpResponse def changelist_view(request): return HttpResponse('列表页面') def add_view(request): return HttpResponse('添加页面') def delete_view(request,nid): return HttpResponse('删除页面') def change_view(request,nid): return HttpResponse('修改页面') url_list = [] for model_class,v in admin.site._registry.items(): # 循环执行每一个类 # 当前类名小写 cls_name = model_class._meta.model_name # 当前类所在的app名称 app_name = model_class._meta.app_label list_url = url(r'^{0}/{1}/$'.format(app_name,cls_name), changelist_view) url_list.append(list_url) add_url = url(r'^{0}/{1}/add/$'.format(app_name, cls_name), add_view) url_list.append(add_url) del_url = url(r'^{0}/{1}/(d+)/del/$'.format(app_name, cls_name), delete_view) url_list.append(del_url) change_url = url(r'^{0}/{1}/(d+)/change/$'.format(app_name, cls_name), change_view) url_list.append(change_url) urlpatterns = [ url(r'^admin/', admin.site.urls), # url(r'^shensong/', ([ # url(r'^login/$',login, name='login'), # ],None,None) ), url(r'^wenfei/', (url_list,None,None,) ), ]
"""s6day102 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url,include from django.contrib import admin from django.shortcuts import HttpResponse def changelist_view(request): return HttpResponse('列表页面') def add_view(request): return HttpResponse('添加页面') def delete_view(request,nid): return HttpResponse('删除页面') def change_view(request,nid): return HttpResponse('修改页面') def get_urls(): temp = [ url(r'^$'.format(app_name, cls_name), changelist_view), url(r'^add/$'.format(app_name, cls_name), add_view), url(r'^del/$'.format(app_name, cls_name), delete_view), url(r'^change/$'.format(app_name, cls_name), change_view) ] return temp url_list = [] for model_class,v in admin.site._registry.items(): # 循环执行每一个类 # 当前类名小写 cls_name = model_class._meta.model_name # 当前类所在的app名称 app_name = model_class._meta.app_label # all_url = url(r'^{0}/{1}/'.format(app_name,cls_name), (get_urls(),None,None,) ) all_url = url(r'^{0}/{1}/'.format(app_name,cls_name), include(get_urls()) ) url_list.append(all_url) urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^shensong/', ([ url(r'^app01/userinfo/$',([ url(r'^$',changelist_view, name='login'), url(r'^add/$',add_view, name='login'), url(r'^(d+)/del/$',delete_view, name='login'), url(r'^(d+)/change/$',change_view, name='login'), ],None,None)), url(r'^app01/usertype/$',([ url(r'^$',changelist_view, name='login'), url(r'^add/$',add_view, name='login'), url(r'^(d+)/del/$',delete_view, name='login'), url(r'^(d+)/change/$',change_view, name='login'), ],None,None)), url(r'^app01/role/$',([ url(r'^$',changelist_view, name='login'), url(r'^add/$',add_view, name='login'), url(r'^(d+)/del/$',delete_view, name='login'), url(r'^(d+)/change/$',change_view, name='login'), ],None,None)), url(r'^app02/article/$', ([ url(r'^$', changelist_view, name='login'), url(r'^add/$', add_view, name='login'), url(r'^(d+)/del/$', delete_view, name='login'), url(r'^(d+)/change/$', change_view, name='login'), ], None, None)), ],None,None) ), url(r'^wenfei/', (url_list,None,None,) ), ]