Part3:视图和模板

一、简述

一个视图就是一个页面,通常提供特定的功能,使用特定的模板。例如:在一个博客应用中,你可能会看到下列视图:

  • 博客主页:显示最新发布的一些内容
  • 博客主页:显示最新发布的一些内容
  • 基于年的博客页面:显示指定年内的所有博客文章
  • 基于月的博客页面:显示指定月内的所有博客文章
  • 基于天的博客页面:显示指定日内的所有博客文章
  • 发布评论:处理针对某篇博客发布的评论

二、编写视图

下面,打开polls/views.py:文件,输入下列代码


from django.shortcuts import render, HttpResponse
def detail(request, question_id):
    return HttpResponse("You‘re looking at question %s." % question_id)

def results(request, question_id):
    response = "You‘re looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You‘re voting on question %s." % question_id)

然后,在polls/urls.py:文件中加入下面的url模式,将其映射到我们上面新增的视图。 from django.conf.urls import url from . import views

urlpatterns = [
    # ex: /polls/
    url(r‘^$‘, views.index, name=‘index‘),
    # ex: /polls/5/
    url(r‘^(?P<question_id>[0-9]+)/$‘, views.detail, name=‘detail‘),
    # ex: /polls/5/results/
    url(r‘^(?P<question_id>[0-9]+)/results/$‘, views.results, name=‘results‘),
    # ex: /polls/5/vote/
    url(r‘^(?P<question_id>[0-9]+)/vote/$‘, views.vote, name=‘vote‘),
]

  现在去浏览器中访问/polls/34/(注意:这里省略了域名。另外,使用了二级路由后,url中都要添加polls部分,参考前面的章节),它将调用detail()函数,然后在页面中显示你在url里提供的ID。访问/polls/34/results/和/polls/34/vote/,将分别显示预定义的伪结果和投票页面

  上面访问的路由过程如下:当有人访问/polls/34/地址时,Django将首先加载mysite.urls模块,因为它是settings文件里设置的根URL配置文件。在该文件里,Django发现了urlpatterns变量,于是在其内按顺序进行匹配。当它匹配上了^polls/,就裁去url中匹配的文本polls/,然后将剩下的文本“34/”,传递给polls.urls进行下一步的处理。在polls.urls中,又匹配到了r’^(?P<question_id>[0-9]+)/$’,最终结果就是调用该模式对应的detail()视图

三、编写能实际干点活的视图

每个视图至少做两件事之一:返回一个包含请求页面的HttpResponse对象或者弹出一个类似Http404的异常。其它的则随你便,你爱干嘛干嘛

下面是一个新的index()视图,用于替代先前无用的index,它会根据发布日期显示最近的5个投票问卷。

from django.http import HttpResponse

from .models import Question

def index(request):
    latest_question_list = Question.objects.order_by(‘-pub_date‘)[:5]
    output = ‘, ‘.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

  这里有个非常重要的问题:在当前视图中的HTML页面是硬编码的。如果你想改变页面的显示内容,就必须修改这里的Python代码。为了解决这个问题,需要使用Django提供的模板系统,解耦视图和模板之间的硬连接。

  首先,在polls目录下创建一个新的templates目录,Django会在它里面查找模板文件。在templates目录中,再创建一个新的子目录名叫polls,进入该子目录,创建一个新的html文件index.html。换句话说,你的模板文件应该是polls/templates/polls/index.html。可以在DJango中直接使用polls/index.html引用该文件。

注意:在Pycharm中,templates文件夹通常已经帮你创建好了!

模板命名空间:

  你也许会想,为什么不把模板文件直接放在polls/templates目录下,而是费劲的再建个子目录polls呢?设想这么个情况,有另外一个app,它也有一个名叫index.html的文件,当Django在搜索模板时,有可能就找到它,然后退出搜索,这就命中了错误的目标,不是我们想要的结果。解决这个问题的最好办法就是在templates目录下再建立一个与app同名的子目录,将自己所属的模板都放到里面,从而达到独立命名空间的作用,不会再出现引用错误。

现在,将下列代码写入文件polls/templates/polls/index.html:

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
    <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

同时,修改视图文件polls/views.py,让新的index.html文件生效:

from django.http import HttpResponse
from django.template import loader
from .models import Question

def index(request):
    latest_question_list = Question.objects.order_by(‘-pub_date‘)[:5]
    template = loader.get_template(‘polls/index.html‘)
    context = {
    ‘latest_question_list‘: latest_question_list,
    }
    return HttpResponse(template.render(context, request))

  上面的代码会加载polls/index.html文件,并传递给它一个参数。这个参数是一个字典,包含了模板变量名和Python对象之间的映射关系。

  在浏览器中通过访问/polls/,你可以看到一个列表,包含“What’s up”的问卷,以及连接到其对应详细内容页面的链接点。

  如果你显示的是No polls are available.说明你前面没有添加Questions对象。没关系,我们手动添加一下就可以。

进入admin界面,选择Questions,点击右上角的Add question,如下操作。

添加完后,刷新/polls/页面。

快捷方式:render()

from django.shortcuts import render
from .models import Question
def index(request):
    latest_question_list = Question.objects.order_by(‘-pub_date‘)[:5]
    context = {‘latest_question_list‘: latest_question_list}
    return render(request, ‘polls/index.html‘, context)

  在实际运用中,加载模板、传递参数,返回HttpResponse对象是一整套再常用不过的操作了,为了节省力气,Django提供了一个快捷方式:render函数,一步到位!看如下代码:

  render()函数的第一个位置参数是请求对象(就是view函数的第一个参数),第二个位置参数是模板。还可以有一个可选的第三参数,一个字典,包含需要传递给模板的数据。最后render函数返回一个经过字典数据渲染过的模板封装而成的HttpResponse对象

四、返回404错误

  现在让我们来编写返回具体问卷文本内容的视图polls/views.py

from django.shortcuts import render, HttpResponse
from django.shortcuts import Http404
from .models import Question

def detail(request, question_id):
    """
    测试Http404
    :param request:
    :param question_id:
    :return:
    """
    try:
        # 获取Question表中的id数据
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, "polls/detail.html", {"question": question})

这里有个新知识点,如果请求的问卷ID不存在,那么会弹出一个Http404错误。

新建polls/detail.html文件,暂时写入下面的代码:

{{ question }}

快捷方式:get_object_or_404()

  就像render函数一样,Django同样为你提供了一个偷懒的方式,替代上面的多行代码,那就是get_object_or_404()方法,参考下面的代码:

polls/views.py

from django.shortcuts import get_object_or_404

def detail(request, question_id):
    """
    测试Http404
    :param request:
    :param question_id:
    :return:
    """
    question = get_object_or_404(Question, pk=question_id)
    return render(request, "polls/detail.html", {"question": question})

  别说我没提醒你,和render一样,也需要从Django内置的快捷方式模块中导出get_object_or_404()

  get_object_or_404()方法将一个Django模型作为第一个位置参数,后面可以跟上任意个数的关键字参数,如果对象不存在则弹出Http404错误。

  同样,还有一个get_list_or_404()方法,和上面的get_object_or_404()类似,只不过是用来替代filter()函数,当查询列表为空时弹出404错误。(filter是模型API中用来过滤查询结果的函数,它的结果是一个列表集。而get则是查询一个结果的方法,和filter是一个和多个的区别!)

五、 使用模板系统

  detail()视图会将上下文变量question传递给对应的polls/templates/polls/detail.html模板,修改该模板的内容,如下所示:

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

  在模板系统中圆点.是万能的魔法师,你可以用它访问对象的属性。在例子{{ question.question_text }}中,DJango首先会在question对象中尝试查找一个字典,如果失败,则尝试查找属性,如果再失败,则尝试作为列表的索引进行查询。

  在 {% for %}循环中的方法调用——question.choice_set.all其实就是Python的代码question.choice_set.all(),它将返回一组可迭代的Choice对象,并用在{% for %}标签中。

  这里我们对Django模板语言有个简单的印象就好,更深入的介绍放在后面。

六、删除模板中硬编码的URLs

  在polls/index.html文件中,还有一部分硬编码存在,也就是href里的“/polls/”部分:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

  它对于代码修改非常不利。设想如果你在urls.py文件里修改了正则表达式,那么你所有的模板中对这个url的引用都需要修改,这是无法接受的!

  我们前面给urls定义了一个name别名,可以用它来解决这个问题。具体代码如下:

<li><a href="{% url ‘detail‘ question.id %}">{{ question.question_text }}</a></li>

  Django会在polls.urls文件中查找name=‘detail‘的url,具体的就是下面这行:

url(r‘^(?P<question_id>[0-9]+)/$‘, views.detail, name=‘detail‘),

  举个栗子,如果你想将polls的detail视图的URL更换为polls/specifics/12/,那么你不需要在模板中重新修改url地址了,仅仅只需要在polls/urls.py文件中,将对应的正则表达式改成下面这样的就行了,所有模板中对它的引用都会自动修改成新的链接:

# 添加新的单词‘specifics‘
url(r‘^specifics/(?P<question_id>[0-9]+)/$‘, views.detail, name=‘detail‘),

七、URL names的命名空间

  本教程例子中,只有一个app也就是polls,但是在现实中很显然会有5个、10个、更多的app同时存在一个项目中。Django是如何区分这些app之间的URL name呢?

  答案是使用URLconf的命名空间。在polls/urls.py文件的开头部分,添加一个app_name的变量来指定该应用的命名空间:

from django.conf.urls import url
from . import views

app_name = ‘polls‘  # 关键是这行
urlpatterns = [
    url(r‘^$‘, views.index, name=‘index‘),
    url(r‘^(?P<question_id>[0-9]+)/$‘, views.detail, name=‘detail‘),
    url(r‘^(?P<question_id>[0-9]+)/results/$‘, views.results, name=‘results‘),
    url(r‘^(?P<question_id>[0-9]+)/vote/$‘, views.vote, name=‘vote‘),
]

现在,让我们将代码修改得更严谨一点,将polls/templates/polls/index.html中的

<li><a href="{% url ‘detail‘ question.id %}">{{ question.question_text }}</a></li>

修改为:

<li><a href="{% url ‘polls:detail‘ question.id %}">{{ question.question_text }}</a></li>

注意引用方法是冒号而不是圆点也不是斜杠!!!!!!!!!!!!

原文地址:https://www.cnblogs.com/xiaohei001/p/9675792.html

时间: 2024-10-09 04:09:23

Part3:视图和模板的相关文章

理解模型,视图,模板

分层(MVC)Model-View-Controller 把一个应用程序以MVC分成几个不封可以给予程序员足够的灵活性,并且鼓励重用diamante.成功的实施了MVC架构的关键在于要正确地分割应用程序的不同层次.芮然在某些情况下,在数据模型里存放如何显示它的信息是贪图一些方便,但是却给将来替换视图带来了极大的困难.同样,在图形布局的代码里放置数据库相关的代码会在替换数据库平台的时候让你头疼不已.------------------------------------Django Django也

JavaScript 应用开发 #2:视图与模板

在用 Backbone 开发的 JavaScript 应用里面,除了模型与集合以外,另一个重要的部分就是视图,英文是 View .在视图里面,我们可以去监听在页面上发生的事件,还有与视图相关的模型和集合的事件,可以去定义处理这些事件用的方法,可以设置包装数据用的元素等等. 模型视图 下面, 先去为 Todo 这个模型的数据创建一个视图,定义这个视图的代码放在 js/Views/TodoView.js 这个文件里面.打开这个文件,输入下面这些代码: var app = app || {}; /**

【python】-- Django路由系统(网址关系映射)、视图、模板

Django路由系统(网址关系映射).视图.模板 一.路由系统(网址关系映射) 1.单一路由对应: 一个url对应一个视图函数(类) urls.py: url(r'^test', views.test), #url(r'^home', views.Test.as_view()), views.py: def test(request): print(request.method) return render(request, "home.html") """

视图调用模板

调用模板分为三步 找到模板 定义上下文 渲染模板 from django.http import HttpResponse from django.template import loader,RequestContext def index(request): # 1.获取模板 template=loader.get_template('booktest/index.html') # 2.定义上下文 context=RequestContext(request,{'title':'图书列表',

Django框架(四):视图、模板

1. 视图 后台管理页面做好了,接下来就要做公共访问的页面了.当我们刚刚在浏览器中输入http://127.0.0.1:8000/admin/之后,浏览器显示出了后台管理的登录页面,那么服务器是如何找到这个页面并返回的呢./admin/是我们想要请求的页面,服务器在收到这个请求之后,就一定对应着一个处理动作,这个处理动作就是帮我们产生页面内容并返回回来,这个过程是由视图来做的. 对于django的设计框架MVT,用户在URL中请求的是视图,视图接收请求后进行处理,并将处理的结果返回给请求者. 1

构建基础的JavaScript MVC——视图和模板(二)

一.动态视图 1.现在渲染视图的方式基本上有2种 (1)服务端生成好html: (2)客户端渲染模板,服务端提供JSON数据接口. 2.客户端渲染视图也有2种方式: (1)使用document.createElement创建Dom元素,然后追加到页面: (2)预先定义HTML静态视图,在必要的时候显示和隐藏HTML片段: 二.模板 1.现在,有很多模板可以选择,比如Mustache.Underscore简单模板.Handlebars.EJS等等.模板引擎简单实用的方法,当然可以自己显示一个小的模

13.django入门01(django入门初探视图,模板,路由)

一.django的基本使用流程. pip install django #安装django 创建一个project: django-admin startproject mysite ---mysite ---settings.py ---url.py ---wsgi.py ---- manage.py(启动文件) 给项目起名字: python mannage.py startapp  app01 django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是

Javascript MVC 学习笔记(三) 视图和模板

模板 Javascript中模板的核心概念是,将包含模板变量的HTML片段和Javascript对象做合并,把模板变量替换为对象中的属性值. 书中讲到了几种库作为模板引擎,但是链接失效了,可以在这里下载,链接:jQuery.tmpl 使用方式很简单,看一下它的说明就行了.给定一个模板,通过给它添加数据就能生成渲染好的元素节点,然后就可以将它添加到页面中,主要使用方法如: //数据 var object = { url: "http://example.com", getName: fu

3、视图和模板

1.在我们的 poll 应用程序中,将有以下四个视图: Poll "index" 页 – 显示最新发布的民意调查. Poll "detail" 页 – 显示一项民意调查的具体问题,不显示该项的投票结果但可以进行投票的 form . Poll "results" 页 – 显示一项给定的民意调查的投票结果. 投票功能 – 为一项给定的民意调查处理投票选项. 在 Django 中,网页及其他内容是由视图来展现的.而每个视图就是一个简单的 Python