更新了Django部分的文档
parent
f3ec671456
commit
acaf60ab5b
|
@ -214,6 +214,7 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
|
||||||
- `models.py`:存放应用的数据模型,即实体类及其之间的关系(MVC/MVT中的M)。
|
- `models.py`:存放应用的数据模型,即实体类及其之间的关系(MVC/MVT中的M)。
|
||||||
- `tests.py`:包含测试应用各项功能的测试类和测试函数。
|
- `tests.py`:包含测试应用各项功能的测试类和测试函数。
|
||||||
- `views.py`:处理请求并返回响应的函数(MVC中的C,MVT中的V)。
|
- `views.py`:处理请求并返回响应的函数(MVC中的C,MVT中的V)。
|
||||||
|
|
||||||
2. 进入应用目录修改视图文件views.py。
|
2. 进入应用目录修改视图文件views.py。
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
|
@ -294,12 +295,15 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
|
||||||
|
|
||||||
```Python
|
```Python
|
||||||
|
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
from io import StringIO
|
depts_list = [
|
||||||
from random import randrange
|
{'no': 10, 'name': '财务部', 'location': '北京'},
|
||||||
|
{'no': 20, 'name': '研发部', 'location': '成都'},
|
||||||
fruits = ['苹果', '草莓', '榴莲', '香蕉', '葡萄', '山竹', '蓝莓', '西瓜']
|
{'no': 30, 'name': '销售部', 'location': '上海'},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
|
@ -310,19 +314,35 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
|
||||||
output.write('\t<title>首页</title>')
|
output.write('\t<title>首页</title>')
|
||||||
output.write('</head>\n')
|
output.write('</head>\n')
|
||||||
output.write('<body>\n')
|
output.write('<body>\n')
|
||||||
output.write('\t<h1>Hello, world!</h1>\n')
|
output.write('\t<h1>部门信息</h1>\n')
|
||||||
output.write('\t<hr>\n')
|
output.write('\t<hr>\n')
|
||||||
output.write('\t<ol>\n')
|
output.write('\t<table>\n')
|
||||||
for _ in range(3):
|
output.write('\t\t<tr>\n')
|
||||||
rindex = randrange(0, len(fruits))
|
output.write('\t\t\t<th>部门编号</th>\n')
|
||||||
output.write('\t\t<li>' + fruits[rindex] + '</li>\n')
|
output.write('\t\t\t<th>部门名称</th>\n')
|
||||||
output.write('\t</ol>\n')
|
output.write('\t\t\t<th>所在地</th>\n')
|
||||||
|
output.write('\t\t</tr>\n')
|
||||||
|
for dept in depts_list:
|
||||||
|
output.write('\t\t<tr>\n')
|
||||||
|
output.write(f'\t\t\t<td>{dept["no"]}</td>\n')
|
||||||
|
output.write(f'\t\t\t<td>{dept["name"]}</td>\n')
|
||||||
|
output.write(f'\t\t\t<td>{dept["location"]}</td>\n')
|
||||||
|
output.write('\t\t</tr>\n')
|
||||||
|
output.write('\t</table>\n')
|
||||||
output.write('</body>\n')
|
output.write('</body>\n')
|
||||||
output.write('</html>\n')
|
output.write('</html>\n')
|
||||||
return HttpResponse(output.getvalue())
|
return HttpResponse(output.getvalue())
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
7. 再次使用下面的命令来启动服务器并查看程序的运行结果。
|
||||||
|
|
||||||
|
```Shell
|
||||||
|
|
||||||
|
(venv)$ cd ..
|
||||||
|
(venv)$ python manage.py runserver
|
||||||
|
```
|
||||||
|
![](./res/runserver.png)
|
||||||
|
|
||||||
#### 使用视图模板
|
#### 使用视图模板
|
||||||
|
|
||||||
上面通过拼接HTML代码的方式生成动态视图的做法在实际开发中是无能接受的,这一点我相信是不言而喻的。为了解决这个问题,我们可以提前准备一个模板页,所谓模板页就是一个带占位符的HTML页面,当我们将程序中获得的数据替换掉页面中的占位符时,一个动态页面就产生了。
|
上面通过拼接HTML代码的方式生成动态视图的做法在实际开发中是无能接受的,这一点我相信是不言而喻的。为了解决这个问题,我们可以提前准备一个模板页,所谓模板页就是一个带占位符的HTML页面,当我们将程序中获得的数据替换掉页面中的占位符时,一个动态页面就产生了。
|
||||||
|
@ -354,14 +374,22 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
|
||||||
<title>首页</title>
|
<title>首页</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>{{ greeting }}</h1>
|
<h1>部门信息</h1>
|
||||||
<hr>
|
<hr>
|
||||||
<h3>今天推荐{{ num }}种水果是:</h3>
|
<table>
|
||||||
<ul>
|
<tr>
|
||||||
{% for fruit in fruits %}
|
<th>部门编号</th>
|
||||||
<li>{{ fruit }}</li>
|
<th>部门名称</th>
|
||||||
{% endfor %}
|
<th>所在地</th>
|
||||||
</ul>
|
</tr>
|
||||||
|
{% for dept in depts_list %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ dept.no }}</td>
|
||||||
|
<td>{{ dept.name }}</td>
|
||||||
|
<td>{{ dept.location }}</td>
|
||||||
|
<tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
@ -379,19 +407,16 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
|
||||||
```Python
|
```Python
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from random import randrange
|
|
||||||
|
depts_list = [
|
||||||
|
{'no': 10, 'name': '财务部', 'location': '北京'},
|
||||||
|
{'no': 20, 'name': '研发部', 'location': '成都'},
|
||||||
|
{'no': 30, 'name': '销售部', 'location': '上海'},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
fruits = ['苹果', '香蕉', '草莓', '葡萄', '山竹', '杨梅', '西瓜', '榴莲']
|
return render(request, 'index.html', {'depts_list': depts_list})
|
||||||
start, end = 0, randrange(len(fruits))
|
|
||||||
ctx = {
|
|
||||||
'greeting': 'Hello, Django!',
|
|
||||||
'num': end + 1,
|
|
||||||
'fruits': fruits[start:end + 1]
|
|
||||||
}
|
|
||||||
return render(request, 'index.html', ctx)
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
到此为止,我们还没有办法让views.py中的render函数找到模板文件index.html,为此我们需要修改settings.py文件,配置模板文件所在的路径。
|
到此为止,我们还没有办法让views.py中的render函数找到模板文件index.html,为此我们需要修改settings.py文件,配置模板文件所在的路径。
|
||||||
|
@ -436,7 +461,6 @@ Django诞生于2003年,它是一个在真正的应用中成长起来的项目
|
||||||
(venv)$ python manage.py runserver
|
(venv)$ python manage.py runserver
|
||||||
```
|
```
|
||||||
|
|
||||||
![](./res/runserver.png)
|
|
||||||
|
|
||||||
### 总结
|
### 总结
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
## Django 2.x实战(02) - 深入模型
|
## Django 2.x实战(02) - 深入模型
|
||||||
|
|
||||||
在上一个章节中,我们提到了Django是基于MVC架构的Web框架,MVC架构追求的是“模型”和“视图的解耦合。所谓“模型”说得更直白一些就是数据,所以通常也被称作“数据模型”。在实际的项目中,数据模型通常通过数据库实现持久化操作,而关系型数据库在很长一段时间都是持久化的首选方案(当然NoSQL的方案在今天普遍被认为是关系型数据库的一个很好的补充),在下面演示的项目中,我们选择使用MySQL来实现数据持久化。
|
在上一个章节中,我们提到了Django是基于MVC架构的Web框架,MVC架构追求的是“模型”和“视图的解耦合。所谓“模型”说得更直白一些就是数据,所以通常也被称作“数据模型”。在实际的项目中,数据模型通常通过数据库实现持久化操作,而关系型数据库在很长一段时间都是持久化的首选方案,下面我们以MySQL为例来说明如何使用关系型数据库来实现持久化操作。
|
||||||
|
|
||||||
### 配置关系型数据库MySQL
|
### 配置关系型数据库MySQL
|
||||||
|
|
||||||
|
我们继续来完善上一个章节中的OA项目,首先从配置项目使用的数据库开始。
|
||||||
|
|
||||||
1. 进入oa文件夹,修改项目的settings.py文件,首先将我们之前创建的应用hrs添加已安装的项目中,然后配置MySQL作为持久化方案。
|
1. 进入oa文件夹,修改项目的settings.py文件,首先将我们之前创建的应用hrs添加已安装的项目中,然后配置MySQL作为持久化方案。
|
||||||
|
|
||||||
```Shell
|
```Shell
|
||||||
|
@ -49,7 +51,7 @@
|
||||||
|
|
||||||
其他的配置可以参考官方文档中[数据库配置](https://docs.djangoproject.com/zh-hans/2.0/ref/databases/#third-party-notes)的部分。
|
其他的配置可以参考官方文档中[数据库配置](https://docs.djangoproject.com/zh-hans/2.0/ref/databases/#third-party-notes)的部分。
|
||||||
|
|
||||||
NAME属性代表数据库的名称,如果使用SQLite它对应着一个文件,在这种情况下NAME的属性值应该是一个绝对路径。如果使用其他关系型数据库,还要配置对应的HOST(主机)、PORT(端口)、USER(用户名)、PASSWORD(口令)等属性。
|
NAME属性代表数据库的名称,如果使用SQLite它对应着一个文件,在这种情况下NAME的属性值应该是一个绝对路径;使用其他关系型数据库,则要配置对应的HOST(主机)、PORT(端口)、USER(用户名)、PASSWORD(口令)等属性。
|
||||||
|
|
||||||
2. 安装MySQL客户端工具,Python 3中使用PyMySQL,Python 2中用MySQLdb。
|
2. 安装MySQL客户端工具,Python 3中使用PyMySQL,Python 2中用MySQLdb。
|
||||||
|
|
||||||
|
@ -132,11 +134,11 @@
|
||||||
mgr = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='主管编号')
|
mgr = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='主管编号')
|
||||||
sal = models.DecimalField(max_digits=7, decimal_places=2, 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='补贴')
|
comm = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True, verbose_name='补贴')
|
||||||
|
# 多对一外键关联
|
||||||
dept = models.ForeignKey(Dept, db_column='dno', on_delete=models.PROTECT, verbose_name='所在部门')
|
dept = models.ForeignKey(Dept, db_column='dno', on_delete=models.PROTECT, verbose_name='所在部门')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'tb_emp'
|
db_table = 'tb_emp'
|
||||||
|
|
||||||
```
|
```
|
||||||
> 说明:上面定义模型时使用了字段类及其属性,其中IntegerField对应数据库中的integer类型,CharField对应数据库的varchar类型,DecimalField对应数据库的decimal类型,ForeignKey用来建立多对一外键关联。字段属性primary_key用于设置主键,max_length用来设置字段的最大长度,db_column用来设置数据库中与字段对应的列,verbose_name则设置了Django后台管理系统中该字段显示的名称。如果对这些东西感到很困惑也不要紧,文末提供了字段类、字段属性、元数据选项等设置的相关说明,不清楚的读者可以稍后查看对应的参考指南。
|
> 说明:上面定义模型时使用了字段类及其属性,其中IntegerField对应数据库中的integer类型,CharField对应数据库的varchar类型,DecimalField对应数据库的decimal类型,ForeignKey用来建立多对一外键关联。字段属性primary_key用于设置主键,max_length用来设置字段的最大长度,db_column用来设置数据库中与字段对应的列,verbose_name则设置了Django后台管理系统中该字段显示的名称。如果对这些东西感到很困惑也不要紧,文末提供了字段类、字段属性、元数据选项等设置的相关说明,不清楚的读者可以稍后查看对应的参考指南。
|
||||||
|
|
||||||
|
@ -157,7 +159,7 @@
|
||||||
Applying hrs.0001_initial... OK
|
Applying hrs.0001_initial... OK
|
||||||
```
|
```
|
||||||
|
|
||||||
执行完数据迁移操作之后,可以在通过图形化的MySQL客户端工具查看到E-R图(实体关系图)。
|
执行完数据模型迁移操作之后,可以在通过图形化的MySQL客户端工具查看到E-R图(实体关系图)。
|
||||||
|
|
||||||
![](./res/er-graph.png)
|
![](./res/er-graph.png)
|
||||||
|
|
||||||
|
@ -435,7 +437,7 @@ Type "help", "copyright", "credits" or "license" for more information.
|
||||||
|
|
||||||
### Django模型最佳实践
|
### Django模型最佳实践
|
||||||
|
|
||||||
1. 正确的模型命名和关系字段命名。
|
1. 正确的为模型和关系字段命名。
|
||||||
2. 设置适当的`related_name`属性。
|
2. 设置适当的`related_name`属性。
|
||||||
3. 用`OneToOneField`代替`ForeignKeyField(unique=True)`。
|
3. 用`OneToOneField`代替`ForeignKeyField(unique=True)`。
|
||||||
4. 通过“迁移操作”(migrate)来添加模型。
|
4. 通过“迁移操作”(migrate)来添加模型。
|
||||||
|
@ -571,7 +573,7 @@ Q对象(用于执行复杂查询)的使用:
|
||||||
>>> Emp.objects.filter(
|
>>> Emp.objects.filter(
|
||||||
... Q(name__startswith='张'),
|
... Q(name__startswith='张'),
|
||||||
... Q(sal__gte=5000) | Q(comm__gte=1000)
|
... Q(sal__gte=5000) | Q(comm__gte=1000)
|
||||||
... ) # 查询名字以“张”开头 工资大于等于5000或补贴大于等于1000的员工
|
... ) # 查询名字以“张”开头且工资大于等于5000或补贴大于等于1000的员工
|
||||||
<QuerySet [<Emp: 张三丰>]>
|
<QuerySet [<Emp: 张三丰>]>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,27 @@
|
||||||
## Django 2.x实战(03) - 请求和响应详解
|
## Django 2.x实战(03) - 请求和响应详解
|
||||||
|
|
||||||
|
基于前面两个章节讲解的知识,我们已经可以使用Django框架来实现Web应用的开发了。接下来我们就尝试实现一个投票应用,具体的需求是用户进入系统首先来到“登录页”;登录成功后可以查看到“学科介绍”页面,该页面显示了一个学校所开设的所有学科;通过点击某个学科,可以进入“讲师详情”页面,该页面展示了该学科所有讲师的详细情况,可以在该页面上给讲师点击“好评”或“差评”;对于未注册的用户,可以在登录页点击“新用户注册”进入“注册页”完成用户注册,注册成功或失败都会获得相应的提示信息,注册成功后会返回“登录页”。
|
||||||
|
|
||||||
|
由于之前已经详细的讲解了如何创建Django项目以及项目的相关配置,因此我们略过这部分内容,唯一需要说明的是,我们将项目命名为`hellodjango`,在项目下创建了一个名为`demo`的应用。从“学科介绍”和“讲师详情”页面的需求,我们可以首先分析出两个业务实体,一个是学科,一个是讲师,二者之前是一对多关联。因此,我们首先修改应用`demo`下的models.py文件来定义数据模型。
|
||||||
|
|
||||||
|
```Python
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
再完成模型迁移之后,我们可以通过下面的SQL语句来添加学科和讲师的数据。
|
||||||
|
|
||||||
|
```SQL
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
接下来,我们就可以修改views.py文件,通过编写视图函数先实现“学科介绍”页面。
|
||||||
|
|
||||||
|
```Python
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 40 KiB |
Loading…
Reference in New Issue