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()
然后我们要在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里面的所有表格 ]