更新了Django第二天的文档

pull/6/head
jackfrued 2018-05-23 08:50:35 +08:00
parent 09a4ec0d10
commit 9eaf6530d5
11 changed files with 405 additions and 48 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
venv venv
.idea .idea
*.pyc *.pyc

View File

@ -1,4 +1,4 @@
## Django实战(01) - 快速上手 ## Django 2.x实战(01) - 快速上手
Web开发的早期阶段开发者需要手动编写每个页面例如一个新闻门户网站每天都要修改它的HTML页面这样随着网站规模和体量的增大这种方式就变得极度糟糕。为了解决这个问题开发人员想到了用外部程序来为Web服务器生成动态内容也就是说HTML页面以及页面中的动态内容不再通过手动编写而是通过程序自动生成。最早的时候这项技术被称为CGI公共网关接口当然随着时间的推移CGI暴露出的问题也越来越多例如大量重复的样板代码总体性能较为低下等因此在呼唤新的英雄的时代PHP、ASP、JSP这类Web应用开发技术在上世纪90年代中后期如雨后春笋般涌现。通常我们说的Web应用是指通过浏览器来访问网络资源的应用程序因为浏览器的普及性以及易用性Web应用使用起来方便简单而且在应用更新时用户通常不需要做任何的处理就能使用更新后的应用而且也不用关心用户到底用的是什么操作系统甚至不用区分是PC端还是移动端。 Web开发的早期阶段开发者需要手动编写每个页面例如一个新闻门户网站每天都要修改它的HTML页面这样随着网站规模和体量的增大这种方式就变得极度糟糕。为了解决这个问题开发人员想到了用外部程序来为Web服务器生成动态内容也就是说HTML页面以及页面中的动态内容不再通过手动编写而是通过程序自动生成。最早的时候这项技术被称为CGI公共网关接口当然随着时间的推移CGI暴露出的问题也越来越多例如大量重复的样板代码总体性能较为低下等因此在呼唤新的英雄的时代PHP、ASP、JSP这类Web应用开发技术在上世纪90年代中后期如雨后春笋般涌现。通常我们说的Web应用是指通过浏览器来访问网络资源的应用程序因为浏览器的普及性以及易用性Web应用使用起来方便简单而且在应用更新时用户通常不需要做任何的处理就能使用更新后的应用而且也不用关心用户到底用的是什么操作系统甚至不用区分是PC端还是移动端。
@ -8,6 +8,8 @@ Web开发的早期阶段开发者需要手动编写每个页面例如一
![](./res/web-application.png) ![](./res/web-application.png)
> 说明:相信有经验的读者会发现,这张图中其实还少了很多东西,例如反向代理服务器、数据库服务器、防火墙等,而且图中的每个节点在实际项目部署时可能是一组节点组成的集群。当然,如果你对这些没有什么概念也不要紧,后续的课程中我们会为大家进行讲解。
| 术语 | 解释 | | 术语 | 解释 |
| ------------- | ------------------------------------------------------------ | | ------------- | ------------------------------------------------------------ |
| **URL/URI** | 统一资源定位符/统一资源标识符,网络资源的唯一标识 | | **URL/URI** | 统一资源定位符/统一资源标识符,网络资源的唯一标识 |
@ -19,13 +21,24 @@ Web开发的早期阶段开发者需要手动编写每个页面例如一
| **Web服务器** | 接受HTTP请求然后返回HTML文件、纯文本文件、图像等资源给请求者 | | **Web服务器** | 接受HTTP请求然后返回HTML文件、纯文本文件、图像等资源给请求者 |
| **Nginx** | 高性能的Web服务器也可以用作[反向代理](https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86)[负载均衡](https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1) 和 [HTTP缓存](https://zh.wikipedia.org/wiki/HTTP%E7%BC%93%E5%AD%98) | | **Nginx** | 高性能的Web服务器也可以用作[反向代理](https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86)[负载均衡](https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1) 和 [HTTP缓存](https://zh.wikipedia.org/wiki/HTTP%E7%BC%93%E5%AD%98) |
#### HTTP协议
### Python的Web框架 这里我们稍微费一些笔墨来谈谈上面提到的HTTP。HTTP超文本传输协议是构建于TCP传输控制协议之上应用级协议它利用了TCP提供的可靠的传输服务实现了Web应用中的数据交换。按照维基百科上的介绍设计HTTP最初的目的是为了提供一种发布和接收[HTML](https://zh.wikipedia.org/wiki/HTML)页面的方法也就是说这个协议是浏览器和Web服务器之间传输的数据的载体。关于这个协议的详细信息以及目前的发展状况大家可以阅读阮一峰老师的[《HTTP 协议入门》](http://www.ruanyifeng.com/blog/2016/08/http.html)、[《互联网协议入门》](http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html)系列以及[《图解HTTPS协议》](http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html)进行了解下图是我于2009年9月10日凌晨4点在四川省网络通信技术重点实验室用开源协议分析工具Ethereal抓包工具WireShark的前身截取的访问百度首页时的HTTP请求和响应的报文协议数据由于Ethereal截取的是经过网络适配器的数据因此可以清晰的看到从物理链路层到应用层的协议数据。
Python的Web框架有上百个比它的关键字还要多。所谓Web框架就是用于开发Web服务器端应用的基础设施通常指封装好的模块和一系列的工具。事实上即便没有Web框架我们仍然可以通过socket或[CGI](https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3)来开发Web服务器端应用但是这样做的成本和代价在实际开发中通常是不能接受的。通过Web框架我们可以化繁为简同时降低创建、更新、扩展应用程序的工作量。Python的Web框架中比较有名的有Flask、Django、Tornado、Pyramid、Bottle、Web2py、web.py等。 HTTP请求请求行+请求头+空行+[消息体]
![](./res/http-request.png)
HTTP响应响应行+响应头+空行+消息体):
![](./res/http-response.png)
> 说明但愿这两张如同泛黄的照片般的截图帮助你大概的了解到HTTP是一个怎样的协议。
### Django概述 ### Django概述
Python的Web框架有上百个比它的关键字还要多。所谓Web框架就是用于开发Web服务器端应用的基础设施通常指封装好的模块和一系列的工具。事实上即便没有Web框架我们仍然可以通过socket或[CGI](https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3)来开发Web服务器端应用但是这样做的成本和代价在实际开发中通常是不能接受的。通过Web框架我们可以化繁为简同时降低创建、更新、扩展应用程序的工作量。Python的Web框架中比较有名的有Flask、Django、Tornado、Pyramid、Bottle、Web2py、web.py等。
在基于Python的Web框架中Django是所有重量级选手中最有代表性的一位开发者可以基于Django快速的开发可靠的Web应用程序因为它减少了Web开发中不必要的开销对常用的设计和开发模式进行了封装并对MVC架构提供了支持MTV。许多成功的网站和App都是基于Django框架构建的国内比较有代表性的网站包括知乎、豆瓣网、果壳网、搜狐闪电邮箱、101围棋网、海报时尚网、背书吧、堆糖、手机搜狐网、咕咚、爱福窝、果库等。 在基于Python的Web框架中Django是所有重量级选手中最有代表性的一位开发者可以基于Django快速的开发可靠的Web应用程序因为它减少了Web开发中不必要的开销对常用的设计和开发模式进行了封装并对MVC架构提供了支持MTV。许多成功的网站和App都是基于Django框架构建的国内比较有代表性的网站包括知乎、豆瓣网、果壳网、搜狐闪电邮箱、101围棋网、海报时尚网、背书吧、堆糖、手机搜狐网、咕咚、爱福窝、果库等。
![](./res/mvc.png) ![](./res/mvc.png)
@ -49,11 +62,11 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
>>> sys.version_info >>> sys.version_info
``` ```
2. 创建项目文件夹并切换到该目录。 2. 创建项目文件夹并切换到该目录例如我们要实例一个OA办公自动化项目
```Shell ```Shell
$ mkdir hello_django $ mkdir oa
$ cd hello_django $ cd oa
``` ```
3. 创建并激活虚拟环境。 3. 创建并激活虚拟环境。
@ -69,7 +82,7 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
```Shell ```Shell
(venv)$ python -m pip install --upgrade pip (venv)$ python -m pip install --upgrade pip
``` ```
> 注意虚拟环境下的python和pip已经是Python 3的解释器和包管理工具了。 > 注意:请注意终端提示符发生的变化,前面的`(venv)`说明我们已经进入虚拟环境,而虚拟环境下的python和pip已经是Python 3的解释器和包管理工具了。
5. 安装Django。 5. 安装Django。
@ -77,7 +90,7 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
(venv)$ pip install django (venv)$ pip install django
``` ```
指定版本号来安装对应的Django的版本。
```Shell ```Shell
(venv)$ pip install django==1.11 (venv)$ pip install django==1.11
@ -95,23 +108,32 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
>>> import django >>> import django
>>> django.get_version() >>> django.get_version()
``` ```
![](./res/django-version.png) 下图展示了Django版本和Python版本的对应关系在我们的项目中我们选择了最新的Django 2.0的版本。
7. 使用`django-admin`创建项目。 | Django版本 | Python版本 |
| ---------- | ----------------------- |
| 1.8 | 2.7、3.2、3.3、3.4、3.5 |
| 1.9、1.10 | 2.7、3.4、3.5 |
| 1.11 | 2.7、3.4、3.5、3.6 |
| 2.0 | 3.4、3.5、3.6 |
> 说明在创建这篇文章时Django 2.1版本尚未正式发布因此我们的教程使用了2.0.5版本。
7. 使用`django-admin`创建项目项目命名为oa。
```Shell ```Shell
(venv)$ django-admin startproject hello_django . (venv)$ django-admin startproject oa .
``` ```
> 注意:上面的命令最后的.表示在当前路径下创建项目。 > 注意:上面的命令最后的那个点,它表示在当前路径下创建项目。
执行上面的命令后看看生成的文件和文件夹,它们的作用如下所示: 执行上面的命令后看看生成的文件和文件夹,它们的作用如下所示:
- `manage.py`: 一个让你用各种方式管理 Django 项目的命令行工具。 - `manage.py`: 一个让你用各种方式管理 Django 项目的命令行工具。
- `hello_django/__init__.py`:一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。 - `oa/__init__.py`:一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。
- `hello_django/settings.py`Django 项目的配置文件。 - `oa/settings.py`Django 项目的配置文件。
- `hello_django/urls.py`Django 项目的 URL 声明,就像你网站的“目录”。 - `oa/urls.py`Django 项目的 URL 声明,就像你网站的“目录”。
- `hello_django/wsgi.py`:作为你的项目的运行在 WSGI 兼容的Web服务器上的入口。 - `oa/wsgi.py`:作为你的项目的运行在 WSGI 兼容的Web服务器上的入口。
8. 启动服务器运行项目。 8. 启动服务器运行项目。
@ -119,32 +141,65 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
(venv)$ python manage.py runserver (venv)$ python manage.py runserver
``` ```
在浏览器中输入<http://127.0.0.1:8000>访问我们的服务器,效果如下图所示。
![](./res/django-index-1.png)
> 说明1刚刚启动的是Django自带的用于开发和测试的服务器它是一个用纯Python编写的轻量级Web服务器但它并不是真正意义上的生产级别的服务器千万不要将这个服务器用于和生产环境相关的任何地方。 > 说明1刚刚启动的是Django自带的用于开发和测试的服务器它是一个用纯Python编写的轻量级Web服务器但它并不是真正意义上的生产级别的服务器千万不要将这个服务器用于和生产环境相关的任何地方。
> 说明2用于开发的服务器在需要的情况下会对每一次的访问请求重新载入一遍Python代码。所以你不需要为了让修改的代码生效而频繁的重新启动服务器。然而一些动作比如添加新文件将不会触发自动重新加载这时你得自己手动重启服务器。 > 说明2用于开发的服务器在需要的情况下会对每一次的访问请求重新载入一遍Python代码。所以你不需要为了让修改的代码生效而频繁的重新启动服务器。然而一些动作比如添加新文件将不会触发自动重新加载这时你得自己手动重启服务器。
> 说明3可以通过`python manage.py help`命令查看可用命令列表;在启动服务器时,也可以通过`python manage.py runserver 1.2.3.4:56789`来指定绑定的IP地址和端口。 > 说明3可以通过`python manage.py help`命令查看可用命令列表;在启动服务器时,也可以通过`python manage.py runserver 1.2.3.4:56789`来指定绑定的IP地址和端口。
9. 创建应用程序(一个项目可以包含多个应用程序)。 > 说明4可以通过Ctrl+C来终止服务器的运行。
9. 接下来我们进入项目目录oa并修改配置文件settings.pyDjango是一个支持国际化和本地化的框架因此刚才我们看到的默认首页也是支持国际化的我们将默认语言修改为中文时区设置为东八区。
```Shell
(venv)$ cd oa
(venv)$ vim settings.py
```
```Python
# 此处省略上面的内容
# 设置语言代码
LANGUAGE_CODE = 'zh-hans'
# 设置时区
TIME_ZONE = 'Asia/Chongqing'
# 此处省略下面的内容
```
10. 回到manage.py所在的目录刷新刚才的页面。
```Shell
(venv)$ cd ..
(venv)$ python manage.py runserver
```
![](./res/django-index-2.png)
#### 动态页面
1. 创建名为hrs人力资源系统的应用一个项目可以包含多个应用
```Shell ```Shell
(venv)$ python manage.py startapp hrs (venv)$ python manage.py startapp hrs
``` ```
创建的目录结构如下所示: 执行上面的命令会在当前路径下创建hrs目录目录结构如下所示:
- `__init__.py`:一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。 - `__init__.py`:一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。
- `admin.py`可以用来注册模型让Django自动创建管理界面。 - `admin.py`可以用来注册模型让Django自动创建管理界面。
- `apps.py`:当前应用的配置。 - `apps.py`:当前应用的配置。
- `migrations`:存放与模型有关的数据库信息。 - `migrations`:存放与模型有关的数据库迁移信息。
- `__init__.py`:略过。 - `__init__.py`一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包
- `models.py`存放应用的数据模型即实体类及其之间的关系MVC/MVT中的M - `models.py`存放应用的数据模型即实体类及其之间的关系MVC/MVT中的M
- `tests.py`:测试应用的各种测试函数。 - `tests.py`包含测试应用各项功能的测试类和测试函数。
- `views.py`处理请求并返回响应的函数MVC中的CMVT中的V - `views.py`处理请求并返回响应的函数MVC中的CMVT中的V
2. 进入应用目录修改视图文件views.py。
#### 动态页面
1. 进入应用目录修改视图文件views.py。
```Shell ```Shell
(venv)$ cd hrs (venv)$ cd hrs
@ -160,7 +215,7 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
``` ```
2. 在应用目录创建一个urls.py文件并映射URL。 3. 在应用目录创建一个urls.py文件并映射URL。
```Shell ```Shell
(venv)$ touch urls.py (venv)$ touch urls.py
@ -176,13 +231,13 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
path('', views.index, name='index'), path('', views.index, name='index'),
] ]
``` ```
> 说明上面使用的path函数是Django 2.0中新添加的函数除此之外还有re_path是支持正则表达式的URL映射函数Django 1.x中是用url函数来设定URL映射。 > 说明上面使用的path函数是Django 2.x中新添加的函数除此之外还有re_path是支持正则表达式的URL映射函数Django 1.x中是用url函数来设定URL映射。
3. 切换到项目目录修改该目录下的urls.py文件合并应用中设定的URL 4. 切换到项目目录修改该目录下的urls.py文件对应用中设定的URL进行合并
```Shell ```Shell
(venv) $ cd .. (venv) $ cd ..
(venv) $ cd hello_django (venv) $ cd oa
(venv) $ vim urls.py (venv) $ vim urls.py
``` ```
@ -196,9 +251,10 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
] ]
``` ```
4. 启动项目并访问应用。 5. 启动项目并访问应用。
```Shell ```Shell
(venv)$ cd ..
(venv)$ python manage.py runserver (venv)$ python manage.py runserver
``` ```
@ -206,7 +262,7 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
> 说明如果想实现远程访问需要先确认防火墙是否已经打开了8000端口而且需要在配置文件settings.py中修改ALLOWED_HOSTS的设置添加一个'*'表示允许所有的客户端访问Web应用。 > 说明如果想实现远程访问需要先确认防火墙是否已经打开了8000端口而且需要在配置文件settings.py中修改ALLOWED_HOSTS的设置添加一个'*'表示允许所有的客户端访问Web应用。
5. 修改views.py生成动态内容。 6. 修改views.py生成动态内容。
```Shell ```Shell
(venv)$ cd hrs (venv)$ cd hrs
@ -245,9 +301,9 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
#### 使用视图模板 #### 使用视图模板
上面生成动态视图的方式在实际开发中是无法接受的,为了解决这个问题我们可以提前准备一个模板页所谓模板页就是一个带占位符的HTML页面当我们将程序中获得的数据替换掉占位符,一个动态页面就生成好了。 上面通过拼接HTML代码的方式生成动态视图的做法在实际开发中是无能接受的这一点我相信是不言而喻的。为了解决这个问题我们可以提前准备一个模板页所谓模板页就是一个带占位符的HTML页面当我们将程序中获得的数据替换掉页面中的占位符时,一个动态页面就生了。
可以用Django框架中template模块的Template类创建模板对象通过模板对象的render方法实现对模板的渲染。所谓的渲染就是用数据替换掉模板页中的占位符Django框架通过shortcuts模块的快捷函数render简化了渲染模板的操作具体的用法如下所示。 我们可以用Django框架中template模块的Template类创建模板对象通过模板对象的render方法实现对模板的渲染。所谓的渲染就是用数据替换掉模板页中的占位符Django框架通过shortcuts模块的快捷函数render简化了渲染模板的操作具体的用法如下所示。
1. 先回到manage.py文件所在的目录创建一个templates文件夹。 1. 先回到manage.py文件所在的目录创建一个templates文件夹。
@ -273,7 +329,7 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
<body> <body>
<h1>{{ greeting }}</h1> <h1>{{ greeting }}</h1>
<hr> <hr>
<h3>今天推荐3种水果是:</h3> <h3>今天推荐{{ num }}种水果是:</h3>
<ul> <ul>
{% for fruit in fruits %} {% for fruit in fruits %}
<li>{{ fruit }}</li> <li>{{ fruit }}</li>
@ -282,6 +338,7 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
</body> </body>
</html> </html>
``` ```
注意在模板页中我们使用了`{{ greeting }}`这样的模板占位符语法,也使用了`{% for %}`这样的模板指令,如果对此不熟悉并不要紧,我们会在后续的内容中进一步的讲解模板的用法。
3. 回到应用目录修改views.py文件。 3. 回到应用目录修改views.py文件。
@ -308,13 +365,13 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
``` ```
这里我们还没有办法让视图找到模板文件index.html需要修改settings.py配置模板文件所在的路径。 此为止我们还没有办法让views.py中的render函数找到模板文件index.html为此我们需要修改settings.py文件配置模板文件所在的路径。
4. 切换到项目目录修改settings.py文件。 4. 切换到项目目录修改settings.py文件。
```Shell ```Shell
(venv)$ cd .. (venv)$ cd ..
(venv)$ cd hello_django (venv)$ cd oa
(venv)$ vim settings.py (venv)$ vim settings.py
``` ```
@ -340,10 +397,17 @@ Django诞生于2003年它是一个在真正的应用中成长起来的项目
# 此处省略下面的内容 # 此处省略下面的内容
``` ```
5. 重新运行项目查看结果。 5. 重新运行项目查看结果。
```Shell ```Shell
(venv)$ cd ..
(venv)$ python manage.py runserver (venv)$ python manage.py runserver
``` ```
![](./res/runserver-1.png) ![](./res/runserver.png)
### 总结
至此我们已经利用Django框架完成了一个非常小的Web应用虽然它并没有任何的实际价值但是我们需要通过这个项目了解到Django框架的使用方式。当然如果使用PyCharm的Professional版本也可以通过PyCharm的创建项目的选项直接创建Django项目使用PyCharm的好处在于编写代码时可以获得代码提示、错误修复、自动导入等功能从而提升开发效率但是代价是需要支付对应的费用才能使用专业版的PyCharm社区版的PyCharm中并未包含对Web框架的支持。
此外学习Django最好的资料肯定是它的[官方文档](https://docs.djangoproject.com/zh-hans/2.0/),除此之外图灵社区最近出版的[《Django基础教程》](http://www.ituring.com.cn/book/2630)也是非常适合初学者的读物。

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,302 @@
## Django实战(02) - 深入模型
在上一个章节中我们提到了Django是一个基于MVC架构的Web框架MVC架构要追求的是模型和视图的解耦合而其中的模型说得更直白一些就是数据所以通常也被称作数据模型。在实际的项目中数据模型通常通过数据库实现持久化操作而关系型数据库在很长一段时间都是持久化的首选方案在我们的OA项目中我们选择使用MySQL来实现数据持久化。
### 配置关系型数据库MySQL
1. 进入oa文件夹修改项目的settings.py文件首先将我们之前创建的应用hrs添加已安装的项目中然后配置MySQL作为持久化方案。
```Shell
(venv)$ cd oa
(venv)$ vim settings.py
```
```Python
# 此处省略上面的代码
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hrs',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'oa',
'HOST': 'localhost',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '123456',
}
}
# 此处省略下面的代码
```
在配置ENGINE属性时常用的可选值包括
- `'django.db.backends.sqlite3'`SQLite嵌入式数据库
- `'django.db.backends.postgresql'`BSD许可证下发行的开源关系型数据库产品
- `'django.db.backends.mysql'`:转手多次目前属于甲骨文公司的经济高效的数据库产品
- `'django.db.backends.oracle'`:甲骨文公司的旗舰关系型数据库产品
其他的配置可以参考官方文档中[数据库配置](https://docs.djangoproject.com/zh-hans/2.0/ref/databases/#third-party-notes)的部分。
NAME属性代表数据库的名称如果使用SQLite它对应着一个文件在这种情况下NAME的属性值应该是一个绝对路径。如果使用其他关系型数据库还要配置对应的USER、PASSWORD、HOST、PORT等属性。
2. 安装MySQL客户端工具Python 3中使用PyMySQLPython 2中用MySQLdb。
```Shell
(venv)$ pip install pymysql
```
如果使用Python 3需要修改**项目**的`__init__.py`文件并加入如下所示的代码这段代码的作用是将PyMySQL视为MySQLdb来使用从而避免Django找不到连接MySQL的客户端工具而询问你“Did you install mysqlclient? ”你安装了mysqlclient吗
```Python
import pymysql
pymysql.install_as_MySQLdb()
```
3. 运行manage.py并指定migrate参数实现数据库迁移为应用程序创建对应的数据表当然在此之前需要先启动MySQL数据库服务器并创建名为oa的数据库在MySQL中创建数据库的语句如下所示。
```SQL
drop database if exists oa;
create database oa default charset utf8;
```
```Shell
(venv)$ cd ..
(venv)$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying sessions.0001_initial... OK
```
4. 可以看到Django帮助我们创建了10张二维表这些都是使用Django框架需要的东西除了这些之外我们还应该为我们自己的应用创建数据模型。如果要在hrs应用中实现对部门和员工的管理我们可以创建如下所示的数据模型。
```Shell
(venv)$ cd hrs
(venv)$ vim models.py
```
```Python
from django.db import models
class Dept(models.Model):
"""部门类"""
no = models.IntegerField(primary_key=True, verbose_name='部门编号')
name = models.CharField(max_length=20, verbose_name='部门名称')
location = models.CharField(max_length=10, verbose_name='部门所在地')
class Meta:
db_table = 'tb_dept'
class Emp(models.Model):
"""员工类"""
no = models.IntegerField(primary_key=True, verbose_name='员工编号')
name = models.CharField(max_length=20, verbose_name='员工姓名')
job = models.CharField(max_length=10, verbose_name='职位')
mgr = models.IntegerField(null=True, blank=True, verbose_name='主管编号')
sal = models.DecimalField(max_digits=7, decimal_places=2, verbose_name='月薪')
comm = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True, verbose_name='补贴')
dept = models.ForeignKey(Dept, on_delete=models.PROTECT, verbose_name='所在部门')
class Meta:
db_table = 'tb_emp'
```
5. 通过模型创建数据表。
```Shell
(venv)$ cd ..
(venv)$ python manage.py makemigrations hrs
Migrations for 'hrs':
hrs/migrations/0001_initial.py
- Create model Dept
- Create model Emp
(venv)$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, hrs, sessions
Running migrations:
Applying hrs.0001_initial... OK
```
执行完数据迁移操作之后可以在通过图形化的MySQL客户端工具查看到E-R图实体关系图
![](./res/er-graph.png)
### 在后台管理模型
### 使用ORM完成模型的CRUD操作
#### 新增
#### 删除
#### 更新
#### 查询
最后,我们通过上面掌握的知识来实现部门展示以及根据获取部门对应员工信息的功能。
### Django模型最佳实践
1. 正确的模型命名和关系字段命名。
2. 设置适当的related_name属性。
3. 用OneToOneField代替ForeignKeyField(unique=True)。
4. 通过迁移操作来添加模型。
5. 用NoSQL来应对需要降低范式级别的场景。
6. 如果布尔类型可以为空要使用NullBooleanField。
7. 在模型中放置业务逻辑。
8. 用ModelName.DoesNotExists取代ObjectDoesNotExists。
9. 在数据库中不要出现无效数据。
10. 不要对QuerySet调用len函数。
11. 将QuerySet的exists()方法的返回值用于if条件。
12. 用DecimalField来存储货币相关数据而不是FloatField。
13. 定义\_\_str\_\_方法。
14. 不要将数据文件放在同一个目录中。
### 模型定义参考
#### 字段
对字段名称的限制
- 字段名不能是Python的保留字否则会导致语法错误
- 字段名不能有多个连续下划线否则影响ORM查询操作
Django模型字段类
| 字段类 | 默认小组件 | 说明 |
| --------------------- | ------------------ | ------------------------------------------------------------ |
| AutoField | 无 | 自增ID字段 |
| BigIntegerField | NumberInput | 64位有符号整数 |
| BinaryField | 无 | 存储二进制数据的字段对应Python的bytes类型 |
| BooleanField | CheckboxInput | 存储True或False |
| CharField | TextInput | 长度较小的字符串 |
| DateField | DateInput | 存储日期有auto_now和auto_now_add属性 |
| DateTimeField | DateTimeInput | 存储日期和日期,两个附加属性同上 |
| DecimalField | TextInput | 存储固定精度小数有max_digits有效位数和decimal_places小数点后面两个必要的参数 |
| DurationField | TextInput | 存储时间跨度 |
| EmailField | TextInput | 与CharField相同可以用EmailValidator验证 |
| FileField | ClearableFileInput | 文件上传字段 |
| FloatField | TextInput | 存储浮点数 |
| ImageField | ClearableFileInput | 其他同FileFiled要验证上传的是不是有效图像 |
| IntegerField | NumberInput | 存储32位有符号整数。 |
| GenericIPAddressField | TextInput | 存储IPv4或IPv6地址 |
| NullBooleanField | NullBooleanSelect | 存储True、False或null值 |
| PositiveIntegerField | NumberInput | 存储无符号整数(只能存储正数) |
| SlugField | TextInput | 存储slug简短标注 |
| SmallIntegerField | NumberInput | 存储16位有符号整数 |
| TextField | Textarea | 存储数据量较大的文本 |
| TimeField | TextInput | 存储时间 |
| URLField | URLInput | 存储URL的CharField |
| UUIDField | TextInput | 存储全局唯一标识符 |
#### 字段属性
通用字段属性
| 选项 | 说明 |
| -------------- | ------------------------------------------------------------ |
| null | 数据库中对应的字段是否允许为NULL默认为False |
| blank | 后台模型管理验证数据时是否允许为NULL默认为False |
| choices | 设定字段的选项,各元组中的第一个值是设置在模型上的值,第二值是人类可读的值 |
| db_column | 字段对应到数据库表中的列名,未指定时直接使用字段的名称 |
| db_index | 设置为True时将在该字段创建索引 |
| db_tablespace | 为有索引的字段设置使用的表空间默认为DEFAULT_INDEX_TABLESPACE |
| default | 字段的默认值 |
| editable | 字段在后台模型管理或ModelForm中是否显示默认为True |
| error_messages | 设定字段抛出异常时的默认消息的字典其中的键包括null、blank、invalid、invalid_choice、unique和unique_for_date |
| help_text | 表单小组件旁边显示的额外的帮助文本。 |
| primary_key | 将字段指定为模型的主键未指定时会自动添加AutoField用于主键只读。 |
| unique | 设置为True时表中字段的值必须是唯一的 |
| verbose_name | 字段在后台模型管理显示的名称,未指定时使用字段的名称 |
ForeignKey属性
1. limit_choices_to
2. related_name
3. relate_query_name
4. to_field
5. db_constraint
6. on_delete
ManyToManyField属性
1. symmetrical
2. through
3. throughfields
4. db_table
#### 模型元数据选项
| 选项 | 说明 |
| --------------------- | ------------------------------------------------------------ |
| abstract | |
| app_label | 如果定义模型的应用不在INSTALLED_APPS中可以用该属性指定 |
| db_table | 模型使用的数据表名称 |
| db_tablespace | |
| default_related_name | 关联对象回指这个模型时默认使用的名称,默认为<model_name>_set |
| get_latest_by | |
| managed | 设置为True时Django在迁移中创建数据表并在执行flush管理命令时把表移除 |
| order_with_respect_to | |
| ordering | 对象的默认排序 |
| permissions | |
| default_permissions | 默认为`('add', 'change', 'delete')` |
| proxy | |
| unique_together | |
| index_together | |
| verbose_name | |
| verbose_name_plural | |
### 数据库API参考
按字段查找可以用的条件:
1. exact / iexact
2. contains / icontains
3. in
4. gt / gte / lt / lte
5. startswith / istartswith / endswith / iendswith
6. range
7. year / month / day / week_day / hour / minute / second
8. isnull
9. search
10. regex / iregex
跨关系查找

View File

@ -1,20 +1,10 @@
from django.db import models from django.db import models
# ORM - 对象关系映射
# 对象模型 <---> 关系模型
# 实体类 <---> 二维表
# 属性 <---> 列
# 对象 <---> 记录
class Dept(models.Model): class Dept(models.Model):
no = models.IntegerField(primary_key=True, verbose_name='部门编号') no = models.IntegerField(primary_key=True, verbose_name='部门编号')
name = models.CharField(max_length=20, verbose_name='部门名称') name = models.CharField(max_length=20, verbose_name='部门名称')
location = models.CharField(max_length=10, verbose_name='部门所在地') location = models.CharField(max_length=10, verbose_name='部门所在地')
# excellent = models.BooleanField(default=0, verbose_name='是否优秀')
def __str__(self):
return self.name
class Meta: class Meta:
db_table = 'tb_dept' db_table = 'tb_dept'

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB