惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Security Blog
Microsoft Security Blog
J
Java Code Geeks
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
N
Netflix TechBlog - Medium
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
Hugging Face - Blog
Hugging Face - Blog
量子位
Blog — PlanetScale
Blog — PlanetScale
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
阮一峰的网络日志
阮一峰的网络日志
D
Docker
罗磊的独立博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
云风的 BLOG
云风的 BLOG
IT之家
IT之家
MyScale Blog
MyScale Blog
Microsoft Azure Blog
Microsoft Azure Blog

陈少文的网站

巨变与机遇的未来十年 Kubernetes 平台管理软件压力测试方案 使用镜像部署 Hexo 静态页面 终于等到你 - GitHub 镜像仓库服务(ghcr.io) 一起来学 Go --(6)Interface 一起来学 Go --(5)Goroutine 和 Channel 什么是函数式编程 如何在 Kubernetes 集群集成 Kata 柯里化与偏函数 使用 PyGithub 自动创建 Label 软件产品是团队能力的输出 Helm 2 、Helm 3 比较 IoT 变现 Kubernetes 中的 DNS 服务 国内的 Helm 镜像源 Harbor 使用自签证书支持 Https 访问 DevOps 工具链之 Prow 如何使用 kfctl 安装 Kubeflow VS Code 无法下载 Go 插件的工具包 工程师更应具有服务精神 你不知道的 Docker 使用技巧 使用 Docker 运行 Tensorflow 论中国 什么是左移 如何清空 Git 仓库全部历史记录 一禅小和尚 有风吹过厨房 时间的玫瑰 如何在 CentOS 安装 GPU 驱动 开发 Tips(19)
Django 浅析与工程目录结构实践
微信公众号 · 2017-01-01 · via 陈少文的网站

1. Django是什么

Django是一套由Python完成的Web开发框架,起初被开发者用于管理以新闻内容为主的网站,2005年7月在BSD许可证发布下开源,2008年6月17日正式成立基金会。与Django一起的Python Web框架还有,Tornado和Flask。

Django提供全套的解决方案,包括但不限于,中间件、缓存、Session、ORM、Auth、后台管理、模板、URL映射等。

2. Django的工作原理

首先介绍一下Django的MTV模式:

  • M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
  • T 代表模板 (Template): 负责如何把页面展示给用户(html)。
  • V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。

那么,当一个http请求发送给一个Django网站时,Django是如何处理的呢?

  1. 中间件收到一个http请求,对请求进行处理。例如,登录状态,参数的转义,合法性验证等。整个网站处理逻辑中通用的部分可以放在中间件处理。

  2. Django在URL分发器中通过正则规则匹配http请求的路径,将请求转发给view函数处理。例如,请求为: http://localhost:8000/index/ ,会匹配到配置的URL路由url(r’^index/$’, ‘myapp.views.index’),意思也就是说,指定了myapp包的views.py文件中的index函数来处理这一类请求。

  3. views中的函数index,处理这个请求,调用Model层提供的方法,获取数据。

  4. MTV模型中对数据的操作是在Model层,只需要让Model的Manager类继承Django的model.Manager类,可以非常方便的对view函数提供接口。Model的Manager类中的方法收到View层的调用后,使用Django封装的ORM,利用对象操作数据库,然后将结果返回给View层。

  5. View层的index函数获取到Model层传回的数据对象后,以参数的形式传给Template。

  6. Template中描述的是数据展示的格式,比如一页多少文章,可不可以编辑等。可以使用for、if等常见的语法格式。Template层收到Model的数据对象之后,将数据渲染成html格式,然后返回给中间件处理。

  7. 中间件会对Response进行最后的处理。例如:静态文件的目录URL、Media文件的URL、还有每个页面都会用到的一些变量,都可以通过中间件写入返回的html中。

  8. 返回给浏览器,呈现给用户。

3. Django的目录结构

3.1 创建Django Project

安装好Django后,使用如下命令创建一个Django项目myproject

1
django-admin startproject myproject

  1. manage.py脚本:用于管理Django站点

  2. 目录myproject

. __init__.py: 用来告诉python,当前目录是python模块

. settings.py: 包含项目的所有配置参数

. urls.py: URL根配置

. wsgi.py: 内置runserver命令的WSGI应用配置

3.2 创建Django App

执行命令,在工程目录下创建两个Django App。

1
2
3
cd myproject
django-admin startapp myapp1
django-admin startapp myapp2

然后,在myproject目录下settings.py文件中的INSTALLED_APPS添加上‘myapp1’,‘myapp2’,以便django给这些app建立数据库表;在myproject目录下urls.py文件中import myapp1, myapp2,在urlpatterns字段添加url(r’^myapp1/’, include(myapp1.urls)), url(r’^myapp2/’, include(myapp2.urls)),告知django哪些url请求分发到这两个app中。

到这里,通常我们就可以去填充myapp1、myapp2中的业务逻辑了,最后执行manager.py syncdb、makemigrations、migrate这些命令创建数据库表就可以将整个网站运行起来了。

3.3 为什么要规范Django的目录结构

如果是一个对可维护性没要求、迭代少的业务,读完上面一部分,就可以了。毕竟,适合的才是最好的,一个简单的业务运用复杂的系统实现是不合理的,理解和学习系统也需要成本。

但是,如果你不仅仅需要写出一个Django Project,而是以后需要写很多的Django Project、频繁地维护这些Project,那么你就需要好好的考虑一下Django Project的目录结构了。如果你在生产环境发布过Django Project,你一定会发现,上面还缺少一部分的讨论,没错,那就是多环境的配置,至少涉及两个环境:本地开发环境和生产环境。多环境怎样去组织你的项目配置文件呢?

一个人要开发和维护很多个Django Project,而一个Django Project有很多个Django App,一个App内部封装了大量的业务逻辑,还有上面提到的多环境配置文件。涉及如此之多的文件,我突然想到了管理学,管理学不就是研究如何计划、组织、领导和控制等行为活动,对所拥有的资源进行整合,然后达到目标的过程吗?我们的目标就是,构建一个易维护、可重用的的Django Project。而管理研究产出的是规范,这就是为什么我要规范Django目录结构的原因

3.4 Django目录结构实践建议

3.4.1 关于粒度 - 一个Django App

Django App是一个完整的,可以处理路由请求、返回响应的功能单元。以最小的、可提供服务的单元作为划分,可以减少复用时学习内部逻辑的成本,同时也可以很好的实现单元之间的隔离。
这样划分粒度对我们构建一个Django App提出要求:能够在App的内部独立完成一次Request请求。

在生产环境中,我们很少从零开始构建一个Django Project,至少从一个内部已有Django Framework开始填充业务逻辑部分。这样考虑是合理的,但是开发人员在PM的催促下匆忙填充业务逻辑,而没有考虑到Django App的拆分,这样就造成每次都需要从原有Django Project拷贝代码,或者从Django Framework开始一次又一次的重复实现功能

3.4.2 怎样去构建一个能够独立完成请求的Django App

重点就是: 每个功能块都使用django-admin创建一个Django App

django已经很明确地告诉我们要怎样构建可以复用的Django App,那就是使用命令行去创建,然后将业务逻辑填充在其中。

使用命令 django-admin startapp myapp1,创建的 Django App 主要有 admin.py、models.py 文件、tests.py 文件、views.py 文件,但这还不够,还需要 forms.py 对表单进行验证;需要 settings.py 对 APP 中的常量进行配置,这里建议常量以 APP 名开头,比如,MYAPP1_XXX 这样;需要 utils.py 放一些工具函数;需要 template 放模板,这里建议在 template 中再创建一个与APP同名的文件夹放模板,这样可以直接拷贝到 Project 的 Template 目录下;还需要 requirements.txt 写依赖文件。
由于有两个 myproject 目录,而子 myproject 内只有几个文件,将其拷贝到与APP同一级目录(需要去掉settings.py文件中包头为myproject.部分)。这样下来,Django 的目录结构就成了这样:

最后是关于多环境的配置:
Django通常会配合Nginx和uwsgi一起部署。可以从uwsgi中获取DJANGO_CONF_MODULE变量值来判断所处的运行环境。
project目录下的setting.py文件,增加如下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
WSGI_ENV = os.environ.get("DJANGO_CONF_MODULE", "")
# 运行模式, DEVELOP(开发模式),PRODUCT(正式模式)
RUN_MODE = 'DEVELOP'
if WSGI_ENV.endswith("production"):
    RUN_MODE = "PRODUCT"
    DEBUG = False
else:
    RUN_MODE = "DEVELOP"
    DEBUG = True
# 加载app中的配置项

from myapp1.settings import *
from myapp2.settings import *

app 目录下的settings.py文件,增加如下内容:

1
2
3
4
5
6
7
# 正式环境配置
if RUN_MODE == 'PRODUCT':
    #设置变量值
    APP_XXX = 'PRODUCT'
else:
    #设置变量值
    APP_XXX = 'DEVELOP'

4. 参考