Django的admin.py注册流程

简介: 通常创建一个Django项目的时候,在Django的配置文件settings.py中,都会有下面的这段配置:INSTALLED_APPS = [ 'django.contrib.admin', 'django.

通常创建一个Django项目的时候,在Django的配置文件settings.py中,都会有下面的这段配置:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
]

这段配置文件是Django用来注册所创建的应用的.

例如这里在创建Django项目时,添加了一个名为"app01"的应用.

在所创建的项目中,存在着一个名为"apps.py"的文件,这个文件的内容如下:

    from django.apps import AppConfig
    
    class App01Config(AppConfig):
        name = 'app01'

在这个文件中,以所注册的应用名加"Config"定义的类中,其实还有一个方法:

    from django.apps import AppConfig
    
    class App01Config(AppConfig):
        name = 'app01'
        
        def ready(self):
            pass

这个ready是程序在执行路由映射之前执行这个方法.那这个函数有什么用呢??

admin.py文件中,可以注册数据库中数据表,这样方便在Django的后台管理所注册的数据库.

admin.site.register(models.UserInfo)

把models.py中的类注册在这里后,就会生成在后台进行管理这个数据表的四个URL.

/admin/app01/userinfo/
/admin/app01/userinfo/add/
/admin/app01/userinfo/1/change/
/admin/app01/userinfo/2/delete/

实际上,把想在Django后台管理的数据表写在admin.py文件中以后,Django会执行一个autodiscover_modules方法.

def autodiscover():
    autodiscover_modules('admin', register_to=site)

Django执行autodiscover_modules后,admin.py文件也就会执行了.

只有admin.py文件执行过后,Django的路由中生成在Django的后台中对已注册的数据表进行增删查改的路由关系映射.

admin执行后,又会执行site函数.

site又会执行什么样的操作呢??进入site函数,在sites.py文件的最后一行,可以看到:

site = AdminSite()

site是AdminSite这个类的一个单例模式.这样一来,执行site方法就相当于执行了AdminSite这个类中的__init__方法.

def __init__(self, name='admin'):
    self._registry = {}
    self.name = name
    self._actions = {'delete_selected': actions.delete_selected}
    self._global_actions = self._actions.copy()
    all_sites.add(self)

执行admin.site方法就相当于实例化一个AdminSite对象,然后这个对象会调用AdminSite这个类中的register方法.

    def register(self, model_or_iterable, admin_class=None, **options):
    
        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:
         
                    options['__module__'] = __name__
                    admin_class = type("%sAdmin" % model.__name__, (admin_class,), options)
    
                self._registry[model] = admin_class(model, self)

register方法的前两个参数都是一个类名.

可以看到register方法的最后会把其参数定义的类加入到__init__方法中_registry方法定义的那个空字典中.

同时对参数中的类进行实例化.

类进行实例化的参数为这个类本身以及site本身.类似下面的情形,

    {
        models.UserInfo: UserInfoAdmin(models.UserInfo,site对象),
        models.UserGroup: ModelAdmin(models.UserGroup,site对象),
    }

同时,由于对AdminSite进行实例化的时候使用了单例模式,所以程序第一次执行完后,系统中会一直存在这个site对象.

这样一来,admin.py程序后,就相当于是把在admin.py中注册的类以及对应的配置文件实例化之后的对象全部封装到AdminSiteregister方法中了.

admin.py执行完成后,Django才开始执行urls.py中配置的路由关系映射.

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', index),
]

如上所示,在路由关系映射中,Django也会再执行一次admin.site.urls的方法.

进入urls方法中,可以看到

@property
def urls(self):
    return self.get_urls(), 'admin', self.name

urls方法是执行了一个get_urls方法.再次进入get_urls方法

    def get_urls(self):
        from django.conf.urls import url, include
        
        ...
    
        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)
        ...
        
        return urlpatterns

get_urls方法中,循环_registry这个字典,为字典中的每个类生成Django后台使用的增删查改等操作的url.

urlpatterns += [
    url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
]
        

在这里,

* model._meta.app_label     表示的是Django中添加的应用名
* model._meta.model_name    表示Django的数据库中的表名

把这两个字符串以"/"进行拼接后生成新的字符串

urlpatterns与这个字符串进行拼接,生成了新的urlpatterns.

在这一行的后边,model_admin又会调用这个对象中的url函数间接执行get_url方法来生成路由关系映射的后半部分.

这个生成的后半部分路由再与前面的新urlpatterns进行拼接,依次循环就生成在Django后台进行数据表操作的路由关系映射.

综上所述,在admin.py中注册models.py中的类的流程

1. 先执行admin.py,使用单例模式创建一个admin.site的对象
2. 在admin.site对象中,把admin.py中定义的类全部注册,并把类中所有的配置全部传递到admin.site对象的_registry生成的字典中
3. 在生成url时,url会循环site中的类,为每一个类生成相应的url

这就是在admin.py中注册数据表后Django的执行流程.

目录
相关文章
|
4月前
|
算法 Docker Python
Python【算法中心 03】Docker部署Django搭建的Python应用流程实例(Docker离线安装配置+Django项目Docker部署)
Python【算法中心 03】Docker部署Django搭建的Python应用流程实例(Docker离线安装配置+Django项目Docker部署)
59 0
|
9月前
|
Python
【django学习】(二)注册新应用与配置settings
【django学习】(二)注册新应用与配置settings
|
10月前
|
关系型数据库 MySQL 数据库
django_连接数据库建立账号注册登陆界面
django_连接数据库建立账号注册登陆界面
95 0
|
11月前
|
数据库 Python
django drf 实现只有超级用户才能注册账号(涉及自定义权限permissions,获取token信息解析token信息)
django drf 实现只有超级用户才能注册账号(涉及自定义权限permissions,获取token信息解析token信息)
|
XML 移动开发 JSON
Win10环境前后端分离项目基于Vue.js+Django+Python3实现微信(wechat)扫码支付流程(2023年最新攻略)
之前的一篇文章:[mpvue1.0+python3.7+Django2.0.4实现微信小程序的支付功能](https://v3u.cn/a_id_112),主要介绍了微信小程序内部支付的流程,然而实际上微信小程序有一定的局限性,也就是用户范围仅限于小程序内部生态圈,在生活中真正具有广泛性、高效性、使用方便性的支付方式还得是扫码支付,扫码的优点在于推广成本低,上至钓鱼台国宾馆,下至发廊地摊都能用,打印出来就完事了,而相比其他支付方式,现金的找零及假钞问题,信用卡的办理门槛、pos机的沉没成本,就算微信可集成的h5支付和小程序支付,奈何很多老年人根本不会用小程序和手机浏览器,更别说再进行支付操作了
Win10环境前后端分离项目基于Vue.js+Django+Python3实现微信(wechat)扫码支付流程(2023年最新攻略)
|
Python
揭开Django管理后台的神秘面纱,实现Model层的注册
实现Model层的注册 假设一个post应用定义了Topic和Comment两个Model,将它们注册到管理后台是非常简单的。下面来看注册Model的方法: 在admin.py文件中声明:❤️ manage的startapp命令在创建post应用的时候会自动创建admin.py文件,想要把自定义的Model注册到管理后台,就需要在这个文件中进行声明:
80 0
揭开Django管理后台的神秘面纱,实现Model层的注册
|
前端开发 JavaScript 数据库
Django+Vue开发生鲜电商平台之7.用户登录和注册功能(下)
基于DRF的前后端分离登录与单独使用Django登录的原理不同,不再需要CSRF验证,DRF提供了许多开箱即用的身份验证方案,并且还允许实现自定义方案。
Django+Vue开发生鲜电商平台之7.用户登录和注册功能(下)
|
前端开发 JavaScript 数据库
Django+Vue开发生鲜电商平台之7.用户登录和注册功能(中)
基于DRF的前后端分离登录与单独使用Django登录的原理不同,不再需要CSRF验证,DRF提供了许多开箱即用的身份验证方案,并且还允许实现自定义方案。
Django+Vue开发生鲜电商平台之7.用户登录和注册功能(中)
|
存储 JSON 算法
Django+Vue开发生鲜电商平台之7.用户登录和注册功能(上)
基于DRF的前后端分离登录与单独使用Django登录的原理不同,不再需要CSRF验证,DRF提供了许多开箱即用的身份验证方案,并且还允许实现自定义方案。
Django+Vue开发生鲜电商平台之7.用户登录和注册功能(上)
|
存储 安全 前端开发
Django API 开发:实现用户登录与注册(下)
现在,我们需要更新身份验证系统以使用令牌。 第一步是更新我们的 DEFAULT_AUTHENTICATION_CLASSES 设置以使用 TokenAuthentication