在Django的官方文档中是这么定义视图的: "一类具有相同功能和模板的网页的集合",概念比较抽象,我们直接 拿比较简单常见论坛网站来举例,可能要求创建以下视图:
在Django中,千万不要把视图理解为前端展示给我们的页面,请大家回顾下Django的MTV 模式。
我们在第二篇公众号中已经演示了最简单视图,在 demo_app/views.py 中
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world. This is your first Django")根据前面的学习我们得知,当我们在浏览器中输入 http://localhost:8000/demo_app/时,Django 的路由规则会将这个请求分配到这个 index这个视图上进行处理,那如果我们输入的url带有参数(如带参数的Get请求)那我们的视图该如何处理呢?看看下面的实例
from django.http import HttpResponse
* 不带参数的视图
def index(request):
return HttpResponse("Hello, world. This is your first Django")
* 带参数的视图
def hello_country(request, country_name):
return HttpResponse("Hello," % country_name)在 demo_app/views.py 中新增 hello_country 的配置新的路由规则:
from django.urls import path
from . import views # . 表示在同级父目录下
urlpatterns = [
path('', views.index, name='index'),
path('hello/<str:country_name>/', views.hello_country, name='hello'),
]
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含 0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的 uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符当浏览器输入 http://localhost:8003/demo_app/hello/china 时,我们新配置的路由规则发挥作用,决定过了 demo_app/views.py 中的 hello_country视图来处理该请求,那我们就会看到页面上返回

在视图中你可以操作数据库,可以使用模板引擎(Django自带的,或者第三方的)等,Django 对视图的要求是返回一个 HttpResponse,或者抛出异常。我们现在就来演示下Django 如何使用模板系统。
我们通过登录到后台管理系统新建几个Cat对象(也可通过Django自带的数据库API),我们将在视图中通过模板使用他们。
首先我们在 demo_app目录下新建templates目录,Django将会在这个目录里查找模板文件。在Django的配置文件中默认设置了 APP_DIRS为True,这一选项会让Django在每个 INSTALLED_APPS文件夹中寻找 templates子目录。
在刚新建的 templates目录里再新建一个目录 demo_app,然后在其中新建 index.html文件。我们在这推荐使用这样的目录结构,虽然我们也可以个把 index.html文件建在 demo_app\templates 目录中。 index.html新建后目录结构如下:
demo_proj/
manage.py
demo_proj/
__init__.py
settings.py
urls.py
wsgi.py
demo_app
migrations
templates
demo_app
index.html
__init__.py
admin.py
apps.py
models.py
test.py
views.py在 demo_app/tempaltes/demp_app/index.html 文件中输入如下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cat List</title>
</head>
<body>
<table border="1">
<tr>
<td>Name</td>
<td>age</td>
</tr>
{% if cats_list %}
{% for cat in cats_list %}
<tr>
<td>{{ cat.name }}</td>
<td>{{ cat.age }}</td>
</tr>
{% endfor %}
{% else %}
<p>No cat</p>
{% endif %}
</table>
</body>
</html>我们更新 demo_app/views.py 文件来调用我们刚才建立的模板
def index(request):
cats_list = Cat.objects.all()
from django.template import loader
template = loader.get_template('demo_app/index.html')
context = {
'cats_list': cats_list,
}
return HttpResponse(template.render(context, request))上面代码的作用,就是载入 demo_app/index.html模板文件,并向该模板传递一个context,这个上下文是个字典,可以理解为 将Python对象 cats_list 映射成 模板内的变量 cats_list,所以,我们在模板中能够引用变量(类似于 {%ifcats_list%}这样的格式{{ xxx }}).
用浏览器 访问 http://127.0.0.1:8003/demo_app/ ,将会看到一个表格,列出了我们新建的几个Cat对象.

回顾下刚才views.py中使用模板的实现过程,我们先载入模板,再填充上下文,最后返回由它生成的 HttpResponse 对象,略显繁琐,Django提供了render() 函数来简化这个流程,我们重新更新 demo_app/views.py 文件
def index(request):
cats_list = Cat.objects.all()
context = {
'cats_list': cats_list,
}
return render(request,'demp_app/index.html',context)重新用浏览器 访问 http://127.0.0.1:8003/demo_app/ ,会返回同样的结果。
回顾下我们的index()视图,它向模板传递了一个 cats_list 变量,我们再来看看 index.html模板中是怎么使用变量的。
{% if cats_list %}
{% for cat in cats_list %}
<tr>
<td>{{ cat.name }}</td>
<td>{{ cat.age }}</td>
</tr>
{% endfor %}
{% else %}
<p>No cat</p>
{% endif %}在模板系统中,我们引用变量的属性都用 {{xx}}, 如 {{cat.name}}, {{cat.age}}。
一些 判断,循环也有固定的格式:
{% for xx in xxx %}
...
...
...
{% end for %}{% if xxxxx %}
{% else %}
{% endif %}http://xxxxx/demo_app/x时进入id=x 的详情页面。其路由配置为from django.urls import path
from . import views # . 表示在同级父目录下
urlpatterns = [
path('', views.index, name='index'),
path('hello/<str:country_name>/', views.hello_country, name='hello'),
path('<int:id>/', views.detail, name='detail'),
]我们将 index.html 改造下,让其显示id,并且id 为超链接
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cat List</title>
</head>
<body>
<table border="1">
<tr>
<td>Id</td>
<td>Name</td>
<td>age</td>
</tr>
{% if cats_list %}
{% for cat in cats_list %}
<tr>
<td><a href = "{% url 'demo_app:dtail' cat.id %}">{{ cat.id }}</a></td>
<td>{{ cat.name }}</td>
<td>{{ cat.age }}</td>
</tr>
{% endfor %}
{% else %}
<p>No cat</p>
{% endif %}
</table>
</body>
</html>以前 href 中的网址 被 {%url'demo_app:detail'cat.id%} 所代替。注意其语法格式:
demo_app:detail 是指 在 demo_app 应用的 urls.py 文件中 name=detail的路由规则。cat.id 则是传入的参数 以空格隔开。模板系统当然还有其他的特定用法,我们会在后面的课程中陆续接触。
我们最后来处理下抛出异常的情况,那我们的detail视图来举例
在 demo_app/views.py添加如下代码
from django.http import Http404
def detail(request, id):
try:
cat = Cat.objects.get(id = id)
except Cat.DoesNotExist:
raise Http404("Cat does not exist")
return render(request, 'demo_app/detail.html',{'cat':cat})根据id 获取具体的cat 对象,如果对象不存在,则抛出404异常 。否则,把获取的cat对象作为上下文传递给 detail.hmtl。代码逻辑很清楚,但Django 还是提供了一个更为简单的函数 get_object_or_404()
from django.shortcuts import render,get_object_or_404()
def detail(request, id):
cat = get_object_or_404(Cat, id=id)
return render(request, 'demo_app/detail.html',{'cat':cat})get_object_or_404() 返回具体对象或者抛出404异常,类似的也有 get_list_or_404()函数,大家可以直接练习下。