分类: Python/Ruby
2013-07-24 21:42:37
1.最的正在用django写个东西,发现关于代码的分析文章还是少一些。
于是自己就出个砖头吧。
在这之前,关于基础要求,还是简单的说一下吧。
首先你要知道python基本的语法。
其次你要有html的基本知识。
最后,你当然要知道django是做什么的了。
千万不要说django就是那个大鸟啊,
被割了,看不到了。
正式开始,
关于django的代码分析,入口要从那儿选呢?
一般我们都是
django-admin.py startproject mysite
python manager.py runserver
不是,那就从上面两个开始吧。
先看看django-admin.py 这个文件吧。实际上我觉得它只是个工具集的入口文件。
基本的感觉是这个样子的。
实际上就是一个常见的command模式。
代码呢,就以django-1.5.1为基准吧。
可以从得到。
先看一下,django/bin/django-admin.py这个文件吧,
有用的就是一句话:
management.execute_from_command_line()
所有的处理都转到了 django.core.management里了。
不过也说明,我们的调用命令的参数是用系统的sys.argv进行处理的,还是感觉跟c/java的不一样,不习惯这种处理,还是少用全局变量的好啊。
不过还是要说一句,sys.argv[0]是命令自己所在的文件既django-admin.py,
argv[1]是startproject,
argv[2]是你的项目名。
现在到django.core.management里看看是怎么回事吧。
首先呢 django.core.management是个目录,那么 execute_from_command_line就是在__init__.py里定义的。
这种定义方式还是在django里很常见的, 不是总是空的__init__.py
def execute_from_command_line(argv=None):
utility = ManagementUtility(argv)
utility.execute()
再看看ManagementUtilty吧。
最重要的就是最后一句
self.fetch_command(subcommand).run_from_argv(self.argv)
得到一个command然后执行,基本上就是一个链式处理,这个在jquery 与 django里还是很常见的,
不过如果是写质量要求比较高的代码,我还是习惯
a = b()
if (NULL != a) {
a.c()
}
深受毒害啊。是不是这种代码写多了,连估算都会变得比较。。。
那么startproject 的command是怎么找到的呢?
看一下fetch_command吧。
def fetch_command(self, subcommand):
里是这样的。
app_name = get_commands()[subcommand]
load_command_class(app_name, subcommand)
如果再仔细看 get_commands就会发现它实际上进行了两种方式的command处理。
1.在django/core/management是的commands下所有的以”_”以外开头的py文件。
2.在settings.INSTALLED_APPS中的子目录management里的 扩展文件。
还有要注意的就是,这个实际上只执行了一次,然后就把_commands这个全局变量给更新了。
也算是一个singleton的模式??
另外就是在load_command_class时,还要注意一下,实际上load的是py文件里的Command类。
这样也就对扩展进行了一定的限制,也就是我们的命令对应的类只能是Command,不是能别的。
如果说灵活性上略差了一点,也可以这么说,实际上,设计从来都是一个中庸,取舍,没有别的花花草草了。
再看看Command吧。基本上的继承结构是像下面这样的
而Command执行基本上就是这样
run_from_argv
→ create_parser()
→ execute() 或者说调用 handle()
而在TemplateCommand是什么呢? 看一下注释吧。
Copies either a Django application layout template or a Django project
layout template into the specified directory.
就是拷贝一下模板,到指定的目录。
如果仔细看一下处理呢,其实还有调用render()的一步,也就是说,实际上还是要对模板还处理一下的。