前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django -- 视图是啥?模板是何物?

Django -- 视图是啥?模板是何物?

作者头像
周辰晨
发布2020-01-20 15:19:30
1K0
发布2020-01-20 15:19:30
举报

前言

在Django的官方文档中是这么定义视图的: "一类具有相同功能和模板的网页的集合",概念比较抽象,我们直接 拿比较简单常见论坛网站来举例,可能要求创建以下视图:

  • 论坛首页 -- 列表页面,由时间先后倒叙展示新建的帖子
  • 帖子详情 -- 详细展示帖子内容
  • 评论处理 -- 为帖子增加评论的操作 在Django 中,系统所展示的页面和其他内容都是由视图派生而来,每一个视图可以表现为一个简单的Python函数,如果是基于类的视图的,则是对应的类中的一个方法。(以上内容也许现在难以理解,耐心看下去就会豁然开朗,^_^) Django 将会根据用户请求的URL来选择使用哪个视图。

在Django中,千万不要把视图理解为前端展示给我们的页面,请大家回顾下Django的MTV 模式。


编写视图

我们在第二篇公众号中已经演示了最简单视图,在 demo_app/views.py

代码语言:javascript
复制
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请求)那我们的视图该如何处理呢?看看下面的实例

代码语言:javascript
复制
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 的配置新的路由规则:

代码语言:javascript
复制
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新建后目录结构如下:

代码语言:javascript
复制
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 文件中输入如下代码:

代码语言:javascript
复制
<!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 文件来调用我们刚才建立的模板

代码语言:javascript
复制
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 文件

代码语言:javascript
复制
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模板中是怎么使用变量的。

代码语言:javascript
复制
{% 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 循环
代码语言:javascript
复制
{% for xx in xxx %}
    ...
    ...
    ...
{% end for %}
  • If 判断 (else 看实际情况)
代码语言:javascript
复制
{% if xxxxx %}



{% else %}


{% endif %}
  • URL 路径 一般当列表页展示时,我们通常可以通过点击其中的一条记录进入到该记录的详情页(detail)。 这边我们假设程序中 detail 页面的视图,模板,路由配置都以配置好,当地址输入 http://xxxxx/demo_app/x时进入id=x 的详情页面。其路由配置为
代码语言:javascript
复制
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 为超链接

代码语言:javascript
复制
<!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添加如下代码

代码语言:javascript
复制
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()

代码语言:javascript
复制
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()函数,大家可以直接练习下。


前文回顾
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师影响力 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 编写视图
  • 模板
  • 模板系统
  • 抛出异常
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档