Django-admin源码流程

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)
app01.models
from django.db import models


class Article(models.Model):
    title = models.CharField(max_length=32)
app02.models

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,) ),

]
示例二


原文地址:https://www.cnblogs.com/ctztake/p/8039973.html