django-admin-url原理

 

我们的django,admin里面,在创建项目的时候,系统内部会自动生成一个url=====>url(r'^admin',admin.site.urls),它仅仅一行代码,在系统内部就自动生成了多个url路径(一张表格一个url路由,然后一个表格一套增删改查路由,也就是说我们每一张表格都是有4个路由,所有有n张表格就有4*n个路由)以及对应的视图和HTML模板,它是怎么做到的,这一行代码里面到底有什么,需要我们进一步去探究,我们要写stark组件的话就需要了解这些,而且还要仿照着admin去写,

如下的代码是核心部分,我们主要是需要实现下面的功能,就是我们把源码分析之后摘出来的最重要的部分,有了下面的代码我们就可以轻松实现上面的那些功能了,

我们要写组件就要重新建立一个app,这个App专门写组件用,在这个app下面建立一个文件夹,文件夹里面建一个文件,文件里面写上如下的代码,

 1 from django.conf.urls import url
 2 from django.shortcuts import HttpResponse,render
 3 
 4 
 5 class ModelSubject(object):
 6     """
 7     我们在这里模拟admin源码里面的ModelAdmin,但是仅仅是其中的一个方法而已,
 8     就是增删改查生成url那一段的方法def get_urls()就是这个方法
 9     """
10     def __init__(self, model, site):
11         self.model = model  # 当我们生成一个实例化对象的时候需要把model这个参数传进来,
12         # 必须要传,它是位置参数,然后我们所传入的那个model就是我们在models.py里面定义的每一个表名也就是类名
13         self.site = site
14 
15     def stand_li(self, request):
16         # 所以我们在这里可以获取到当前的url里面的表名,然后直接使用orm语句即可得到当前表格的所有信息
17         ret = self.model.objects.all()
18         return render(request, 'file/hello.html', locals())
19 
20     def add_view(self, request):
21         return HttpResponse('add')
22 
23     def edit_view(self, request):
24         return HttpResponse('edit')
25 
26     def dele_view(self, request):
27         return HttpResponse('dele')
28 
29     def get_urls(self):
30         temp = []
31         temp.append(url(r'^$', self.stand_li))
32         temp.append(url(r'^dele/', self.dele_view))
33         temp.append(url(r'^edit/', self.edit_view))
34         temp.append(url(r'^add/', self.add_view))
35         return temp
36 
37     @property
38     def urls(self):
39         return self.get_urls()
40 
41 
42 class Stark(object):
43     """
44     我们这里面的功能是可以跟上面的类写到一起去的,但是我们为了功能解耦,所以就分开写了,这里的主要功能就是
45     生成registry的字典,把键值对生成,然后我们最终的结果是要得到一个实例化对象,供我们后面的程序调用,这里的类才是主要的,核心的代码块
46     而我们上面的那个ModelSubject是辅助我们这里的功能,它之所以分发出去是为了便于扩展其他的功能,我们的自定义样式,
47     还有很多的方法和参数,就像我们的admin里面的ModelAdmin一样,长达1400多行代码,单独把它分离出去便于功能的扩展
48     """
49 
50     def __init__(self):
51         self._registry = {}  # 这里是定义一个私有属性,就是为了避免被子类修改
52 
53     def register(self, model, model_config=None):  # 我们是仿照着admin的源码写的组件,这里的model_config默认值是None,
54         # 我们在传参的时候,如果给它传值,那么就使用我们传入的值替换掉这个None
55         # 它的源码里面有这几个参数,我们也要按照顺序把这几个参数加进来
56         if not model_config:
57             model_config = ModelSubject  # 我们这里的model_config我们上面的类ModelSubject实例化出来的对象,
58             # 它是上面的类所实例化出来的对象,这一句写得明明白白的,这大白话再看不懂就真是白学了,
59         self._registry[model] = model_config(model, self)
60 
61     def get_urls(self):
62         li = []
63         for model, model_config in self._registry.items():  # 我们在这里所循环的model_config就是
64             # 我们往上数第四行所实例化出来的那个model_config,它是上面的ModelSubject这个类所实例化出来对象,
65             model_name = model._meta.model_name  # 这里的._meta.model_name是获取字符串格式的类名,
66             app_label = model._meta.app_label  # 这里的._meta.app_labe获取的是字符串格式的App名,都是为了跟url做匹配,
67             sli = url(r'%s%s/' % (app_label, model_name), (model_config.urls, None, None))  # 我们这里的model_config,
68             # 它后面的.urls是在调用一个私有方法,我们的私有方法就是使用.urls来调用,不用加上括号,
69             # 因为有@property这个装饰器在里面起到的作用,然后我们需要找到model_config这个实例对象是哪个类生成的,
70             # 然后找到该类所拥有的方法,从里面找到urls,届时,那个urls就是我们在这里调用的那个urls了,
71             # 所以关键的点就是我们的model_config,老师讲课的时候一再地强调过这个model_config从何而来,这个是关键,
72             li.append(sli)
73         return li
74 
75     # 我们最终的数据结构就是这样的,嵌套多层
76     # [
77     # url(
78     # r'',(
79     # [
80     # (url(r'',views.add)),
81     # (url(r'',views.edit)),
82     # ],
83     # none,none)
84     # )
85     # ]
86     @property
87     def urls(self):
88         return self.get_urls(), None, None
89 
90 
91 site = Stark()
admin-url仿写

 

然后我们要在setting里面把新建的App都配置好,在这个组件的App里面找到apps.py文件,配置上如下代码:

from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules


class FileConfig(AppConfig):
    name = 'file'  # 这里的name属性是自动生成的,我们就不用动它了
# 下面的函数是自己后来加上的,ready是固定格式,就要叫这个函数名,然后下
# 面的代码也是固定格式,所传的参数要跟上面的name属性值一致
    def ready(self):
        autodiscover_modules('file')  # 这里是自动扫描的意思,系统会自动把所有名字带file的文件都加载出来,
        # 扫描即加载的意思,这个名字就是随意起的,但是前提是你必须要对应上才可以,文件名和文件夹的名字

 

再去每个App项目里面建立一个py文件,文件名就叫我们上面apps.py里面的类的静态属性值,这里是''file'',

然后在这个文件里面写配置项:

from file.tool.tag import site  # 这里是把我们上面的那个核心文件里面的实例化对象引入到这里来,这个site就是,
from .models import *  # 把所有的表格导入
site.register(Book)  # 注册表格

 

我们项目的url配置:

from django.conf.urls import url
from django.contrib import admin
from file.tool.tag import site
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^stark/', site.urls)  # 这里主要是模拟上面的admin,我们就写这一句话,然后就可以访问到我们在model里面的所有表格

]

 

posted @ 2018-03-12 19:37  dream-子皿  阅读(830)  评论(0)    收藏  举报