加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Django--admin源码流程

发布时间:2020-12-15 17:20:08 所属栏目:大数据 来源:网络整理
导读:div class="postBody" div id="cnblogs_post_body" class="blogpost-body" admin.py url.py = 以上两个文件都引用的是django.contrib.admin.site中的方法,site是AdminSite实例化出来的一个对象,所以site调用的register方法和urls属性(方法被@property装饰

<div class="postBody">
<div id="cnblogs_post_body" class="blogpost-body">

admin.py

url.py

=

以上两个文件都引用的是django.contrib.admin.site中的方法,site是AdminSite实例化出来的一个对象,所以site调用的register方法和urls属性(方法被@property装饰器装饰)是AdminSite这个类中定义的

在源码AdminSite这个类的构造方法初始化定义了一个空字典 _registry={}

admin_class instance

看源码中的admin.site.register函数如下

    def register(self,model_or_iterable,admin_class=None,**        Registers the given model(s) with the given admin     The model(s) should be Model classes,not instances.

    If an admin </span><span style="color: #0000ff;"&gt;class</span> isn<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;t given,it will use ModelAdmin (the default</span>
    admin options). If keyword arguments are given -- e.g.,list_display --<span style="color: #000000;"&gt;
    they</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;ll be applied as options to the admin class.</span>

<span style="color: #000000;">
If a model <span style="color: #0000ff;">is already registered,<span style="color: #0000ff;">this<span style="color: #000000;"> will raise AlreadyRegistered.

    If a model </span><span style="color: #0000ff;"&gt;is</span> <span style="color: #0000ff;"&gt;abstract</span>,<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt; will raise ImproperlyConfigured.
    </span><span style="color: #800000;"&gt;"""

<span style="color: #ff0000;"> if not admin_class:
admin_class = ModelAdmin

    </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; isinstance(model_or_iterable,ModelBase):
        model_or_iterable </span>=<span style="color: #000000;"&gt; [model_or_iterable]
    </span><span style="color: #0000ff;"&gt;for</span> model <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; model_or_iterable:
        </span><span style="color: #0000ff;"&gt;if</span> model._meta.<span style="color: #0000ff;"&gt;abstract</span><span style="color: #000000;"&gt;:
            raise ImproperlyConfigured(
                </span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;The model %s is abstract,so it cannot be registered with admin.</span><span style="color: #800000;"&gt;'</span> %<span style="color: #000000;"&gt; model.__name__
            )

        </span><span style="color: #0000ff;"&gt;if</span> model <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; self._registry:
            raise AlreadyRegistered(</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;The model %s is already registered</span><span style="color: #800000;"&gt;'</span> %<span style="color: #000000;"&gt; model.__name__)

        # Ignore the registration </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; the model has been
        # swapped </span><span style="color: #0000ff;"&gt;out</span><span style="color: #000000;"&gt;.
        </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; not model._meta.swapped:
            # If we got </span>**<span style="color: #000000;"&gt;options then dynamically construct a subclass of
            # admin_class with those </span>**<span style="color: #000000;"&gt;options.
            </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; options:
                # For reasons I don</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;t quite understand,without a __module__</span>
                # the created <span style="color: #0000ff;"&gt;class</span> appears to <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;live</span><span style="color: #800000;"&gt;"</span> <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; the wrong place,# which causes issues later on.
                options[</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;__module__</span><span style="color: #800000;"&gt;'</span>] =<span style="color: #000000;"&gt; __name__
                admin_class </span>= type(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;%sAdmin</span><span style="color: #800000;"&gt;"</span> %<span style="color: #000000;"&gt; model.__name__,(admin_class,),options)

            # Instantiate the admin </span><span style="color: #0000ff;"&gt;class</span> to save <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; the registry
            <span style="color: #ff0000;"&gt;self._registry[model] </span></span><span style="color: #ff0000;"&gt;= admin_class(model,self)</span></pre>

<div class="cnblogs_code_toolbar">

register函数第一个参数是注册的模块名称,第二个参数不传默认是None,但是实际使用的是ModelAdmin,ModelAdmin已模块名称作为参数实例化得到的对象作为 registry字典的value。简化如下:

def register(self,**=</span><span style="color: #0000ff;"&gt;for</span> model <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; model_or_iterable:
    .......
    .......
    self._registry[model] </span>= admin_class(model,self)</pre>

<div class="cnblogs_code_toolbar">

 django.contrib.contenttypes import views def wrap(view,cacheable</span>=<span style="color: #000000;"&gt;False):
    ......
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; update_wrapper(wrapper,view)

# Admin</span>-site-<span style="color: #000000;"&gt;wide views.
urlpatterns </span>=<span style="color: #000000;"&gt; [
    url(r</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;^$</span><span style="color: #800000;"&gt;'</span>,wrap(self.index),name=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;index</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;),url(r</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;^login/$</span><span style="color: #800000;"&gt;'</span>,self.login,name=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;login</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;),url(r</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;^logout/$</span><span style="color: #800000;"&gt;'</span>,wrap(self.logout),name=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;logout</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;),url(r</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;^password_change/$</span><span style="color: #800000;"&gt;'</span>,wrap(self.password_change,cacheable=True),name=<span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;password_change</span><span style="color: #800000;"&gt;'</span><span style="color: #000000;"&gt;),......
]

valid_app_labels </span>=<span style="color: #000000;"&gt; []
</span><span style="color: #0000ff;"&gt;for</span> model,model_admin <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; self._registry.items():
    urlpatterns </span>+=<span style="color: #000000;"&gt; [
        url(r</span><span style="color: #800000;"&gt;'</span><span style="color: #800000;"&gt;^%s/%s/</span><span style="color: #800000;"&gt;'</span> %<span style="color: #000000;"&gt; (model._meta.app_label,model._meta.model_name),include(model_admin.urls)),]
    </span><span style="color: #0000ff;"&gt;if</span> model._meta.app_label not <span style="color: #0000ff;"&gt;in</span><span style="color: #000000;"&gt; valid_app_labels:
        valid_app_labels.append(model._meta.app_label)
    ......

</span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; urlpatterns

@property
def urls(self):
<span style="color: #0000ff;">return self.get_urls(),<span style="color: #800000;">'<span style="color: #800000;">admin<span style="color: #800000;">',self.name #返回的是一个元组
<div class="cnblogs_code_toolbar">

首先urls是个函数被@property装饰器装饰为属性,

,如下

会根据下面的代码添加到urlpatterns中

model,model_admin += %

model_class._meta.app_label 代表model所在的模块名比如app01
model_class._meta.model_name 代表model对应的表的小写名,比如userinfo

这样就生成了/app01/userinfo/ 这样的url前缀。

后面调用的include(model_admins.urls) 中的model_admins.urls 即执行的是self._registry['UserInfo'].urls =====admin_class(model,self).urls=======admin_class这个类生成对象的urls属性【此时这个对象是UserInfo的对象,所以下面get_url函数中的self指的就是UserInfo的对象】======admin_class这个类的urls属性========= >ModelAdmin这个类的urls属性【

def wrap(view):
    def wrapper(</span>*args,**<span style="color: #000000;"&gt;kwargs):
        </span><span style="color: #0000ff;"&gt;return</span> self.admin_site.admin_view(view)(*args,**<span style="color: #000000;"&gt;kwargs)
    wrapper.model_admin </span>=<span style="color: #000000;"&gt; self
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; update_wrapper(wrapper,view)

info </span>=<span style="color: #000000;"&gt; self.model._meta.app_label,self.model._meta.model_name

<span style="color: #ff0000;"> urlpatterns <span style="color: #ff0000;">= [
url(r'^$',wrap(self.changelistview),name='%s%s_changelist' % info),url(r'^add/$',wrap(self.addview),name='%s%s_add' % info),# self代表的是UserInfo的对象
url(r'^(.+)/history/$',wrap(self.historyview),name='%s%s_history' % info),url(r'^(.+)/delete/$',wrap(self.deleteview),name='%s%s_delete' % info),url(r'^(.+)/change/$',wrap(self.changeview),name='%s%s_change' % info),# For backwards compatibility (was the change url before 1.9)
url(r'^(.+)/$',wrap(RedirectView.as_view(
patternname='%s:%s%s_change' % ((self.admin_site.name,) + info)
))),]
<span style="color: #0000ff;">return<span style="color: #000000;"> urlpatterns

@property
def urls(self):
<span style="color: #0000ff;">return self.get_urls()
<div class="cnblogs_code_toolbar">

同理,urls是个被@property装饰的属性,调用ModelAdmin类自身的get_urls函数的时候返回的即是,这样和上面形成的url路径拼接即可得到如下的效果

urlpatterns =,name= %,name= %,name= %,name= %,name= %= % ((self.admin_site.name,) +

当然也可以自定制ModelAdmin,如下

<span style="color: #0000ff;">class<span style="color: #000000;"> UserInfoModelAdmin(ModelAdmin):
# 没有super 是这个类只定义了一个方法,没有继承其他的?还是继承了所有,只覆盖了这一个呢?
# 自定义功能
def changelist_view(self,request,
*args,**<span style="color: #000000;">kwargs):
<span style="color: #0000ff;">return
HttpResponse(<span style="color: #800000;">'
<span style="color: #800000;">用户列表
<span style="color: #800000;">'
<span style="color: #000000;">)

admin.site.register(models.UserInfo,UserInfoModelAdmin)
<span style="color: #0000ff;">class<span style="color: #000000;"> UserTypeModelAdmin(ModelAdmin):
pass

admin.site.register(models.UserType,UserTypeModelAdmin)


<div class="cnblogs_code_toolbar">

继承自ModelAdmin,并重写了changelist_view 这个方法,父类 其他的继承了吗?==

所以上面这张register的方法可以如下理解:

在admin.site对象的 _registry ===/admin/app01/userinfo//admin/app01/userinfo/add//admin/app01/userinfo/(d+)/delete//admin/app01/userinfo/(d+)/change/=models.UserType: obj2 </span>=<span style="color: #000000;"&gt; ModelAdmin(models.UserType,#obj2 和上面说的同理,代表的是UserType对象
</span>/admin/app01/usertype/<span style="color: #000000;"&gt;                obj2.changelist_view
</span>/admin/app01/usertype/add/<span style="color: #000000;"&gt;            obj2.add_view
</span>/admin/app01/usertype/(d+)/delete/<span style="color: #000000;"&gt;   obj2.delete_view
</span>/admin/app01/usertype/(d+)/change/<span style="color: #000000;"&gt;   obj2.change_view
                                      self.model</span>=<span style="color: #000000;"&gt;models.UserType

}

<span style="color: #0000ff;">for model,model_admin <span style="color: #0000ff;">in<span style="color: #000000;"> self._registry.items():
urlpatterns +=<span style="color: #000000;"> [

url(r<span style="color: #800000;">'<span style="color: #800000;">^%s/%s/<span style="color: #800000;">' %<span style="color: #000000;"> (model._meta.app_label,url(r<span style="color: #800000;">'<span style="color: #800000;">^%s/%s/<span style="color: #800000;">' % (<span style="color: #800000;">'<span style="color: #800000;">app01<span style="color: #800000;">',<span style="color: #800000;">'<span style="color: #800000;">userinfo<span style="color: #800000;">'<span style="color: #000000;">),]

<div class="cnblogs_code_toolbar">

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!