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

推荐订阅源

N
News and Events Feed by Topic
V
V2EX
博客园 - 【当耐特】
Vercel News
Vercel News
雷峰网
雷峰网
爱范儿
爱范儿
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Azure Blog
Microsoft Azure Blog
F
Full Disclosure
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
NISL@THU
NISL@THU
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Microsoft Security Blog
Microsoft Security Blog
腾讯CDC
P
Proofpoint News Feed
B
Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
K
Kaspersky official blog
I
InfoQ
Google Online Security Blog
Google Online Security Blog
L
LINUX DO - 最新话题
Project Zero
Project Zero
Engineering at Meta
Engineering at Meta
V
Visual Studio Blog
AI
AI
Schneier on Security
Schneier on Security
B
Blog RSS Feed
T
Tor Project blog
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
S
Security @ Cisco Blogs
T
Threat Research - Cisco Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
C
Cyber Attacks, Cyber Crime and Cyber Security
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
V2EX - 技术
V2EX - 技术
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
Arctic Wolf
Webroot Blog
Webroot Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main

陈少文的网站

巨变与机遇的未来十年 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) 使用 Velero 备份 Kubernetes 集群 Kubernetes Cheat Sheet 开发 Tips(18) 如何构建一个 Java 工程 开发 Tips(17) KubeSpray 安装 Kubernetes 报错 ip in ansible_all_ipv4_addresses 基于 Kubernetes 和 Jenkins 搭建自动化测试系统 在 Kubernetes 上动态创建 Jenkins Slave 使用 Jenkins 进行服务拨测 开发 Tips(16) Kubernetes 签发 Ingress 证书及日常故障运维 Kubernetes 中 Deployment 的基本操作 Kubernetes 中的证书 如何使用 KubeBuilder 开发一个 Operator Kubernetes 1.6.0 安装问题汇总 镜像管理工具 -- Harbor 开发 Tips(15) Docker 如何拉取镜像 开发 Tips(14) 使用 Helm 安装 harbor 开发 Tips(13) 使用 S2I 构建云原生应用 在 Kubernetes 中使用 emptyDir、hostPath、localVolume 开发 Tips(12) 开发 Tips(11) 代码质量分析工具 SonarQube 使用 Kubeadm 安装 Kubernetes 集群 一起来学 Go --(4)常用函数 Kubernetes 中的 Ceph Kubernetes 之 Volumes Kubernetes 之 Labels、Selectors 开发 Tips(10) 开源正在重构商业模式 Kubernetes 之网络 Kubernetes 之 API 使用 Helm 和 Operator 快速部署 Prometheus Kubernetes 复杂有状态应用管理框架 -- Operator Kubernetes 的包管理器 -- Helm 一起来学 Go --(3)Go Modules 如何一步一步地优化博客方案 kubectl 实用指南 Kubernetes 中的基本概念 搭建远程 Kubernetes 开发环境 大公司和小公司的 ToB 思路 开发 Tips(9) Go 入门指南 一起来学 Go --(2)数据与逻辑结构 如何预防 Web 富文本中的 XSS 攻击 django-xss-cleaner 云工作时代 一起来学 Go --(1)背景与特点 SaaS 开发团队的不同阶段 你不知道的 Git 使用技巧 输出既服务 微服务设计 继续奔跑 开发 Tips(8) 从账户安全到二次验证 Django 性能之数据库查询优化 Django 性能之分库分表 敏捷开发之研发流程 打造一致性的团队 开发 Tips(7) Pytest 进阶学习之 Mock PaaS 部署之 buildpack Go 开发配置 领域输出才是 PaaS 的核心竞争力 Pytest 入门学习 开发 Tips(6) 如何使用 Jenkins、Docker、GitLab 搭建 Django 自动化部署流程
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. 参考