博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[译]Django first steps Part3
阅读量:5058 次
发布时间:2019-06-12

本文共 6423 字,大约阅读时间需要 21 分钟。


我们将继续part2中的polls应用,继续创建对外接口views

1 概述

一个views是django应用中web页面的一个“类型”,一般服务于一个特定函数和一个特定的模板,举个例子,在一个blog的应用中,可能拥有下面几个views:

  • blog主页,显示一些最新的文章入口
  • “detail”页面入口,用于每片文章的永久链接
  • 年归档页面,给定年份的每个月入口
  • 月归档页面,给定月的每日入口
  • 日归档页面,给定天的文章入口
  • 评论,处理提交评论到指定的入口

在我们的polls应用中,我们需要下面的几个views:

  • Question “index”页面,显示最新的几个问题
  • Question “detail” 页面,显示问题内容,不显示结果但是有一个投票的form表单提交框
  • Question “results” 页面,显示特定问题的投票结果
  • vote动作,处理投票,特定的选择绑定到特定的问题上

在django中,web页面和其他内容都是有views实现的。每个view相当与一个简单的python函数(如果是基于class的话就是类中的一个方法)。django通过遍历url来选择view。

django提供了更优雅的url,如/newsarchive/<year>/<month>/,而不是ME2/Sites/dirmod.asp?sid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B

要从url得到view,django使用了URLconfs,一个URLconf指向了一个URL样式(使用正则表达式编写)到一个view。


2 编写更多的view

修改polls/views.py文件:

from django.shortcuts import HttpResponsedef index(request):    return HttpResponse("Hello, world. You're at the polls index.")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文件:

from django.conf.urls import urlfrom . import viewsurlpatterns = [    url(r'^$',views.index,name="index"),    url(r'^(?P
[0-9]+)/$',views.detail,name="detail"), url(r'^(?P
[0-9]+)/results/$',views.results,name="results"), url(r'^(?P
[0-9]+)/vote/$',views.vote,name="vote"),]

打开浏览器,/polls/34/将运行detail(),当有人请求页面的时候,说“/polls/34/ ”,django将会加载“mysite.urls ”,因为在settings里面的“ROOT_URLCONF”的设置。它会按顺序找到“urlpatterns ”参数对应的正则表达式匹配的url,首先匹配到’^polls/’, 然后到‘polls.urls’中匹配到"34/" – r’^(?P[0-9]+)/$’, 并将url中的参数映射给 detail() view:

detail(request=
, question_id='34')

(?P<question_id>[0-9]+)中的question_id将作为参数传给view中的函数,[0-9]+表示一个或多个数字。当然,也可以直接使用html来作为url,如下:

url(r'^polls/latest\.html$', views.index),

但是,不要这么弄,这样太傻了。

3 写view到底干了啥

每一个view负责做下面两件事情中的一件:

  • 返回一个包含内容的HttpResponse 对象

  • 返回一个例外,如http404

你的view能够读取数据库中的记录,能够使用django的template系统或第三方模板系统,能够生成一个pdf文件,输出xml,创建一个zip文件,通过使用python的库得到你所想要的任何东西。

django需要的只是HttpResponse 对象,现在我们来修改一下part2中的index(),用来列举最近的5个问题。

#_*_coding:utf-8_*_from django.shortcuts import HttpResponsefrom . import modelsdef index(request):    #倒排所有的question问题,只取前五个    latest_question_list = models.Question.objects.order_by("-pub_date")[:5]    #合并列表,中间用","隔开    output = ', '.join([q.question_text for q in latest_question_list])    return HttpResponse(output)

但是有一个问题:view使用硬编码(hard-coded)方式编写,如果你想要修改页面就需要修改python代码,所以django使用template模板系统来显示页面。

首先创建一templates的目录在polls下面,django会在这里边找模板,你的工程中TEMPLATES 设置描述了django如何加载和渲染模板, describes how Django will load and render templates. 默认设置一个 DjangoTemplates backend 中 APP_DIRS 为True. DjangoTemplates 将会在每个INSTALLED_APPS中寻找 “templates” 。

在template下再创建一个polls的文件夹,以后可以通过polls/index.html来访问模板文件。

Template的命名

我们可以将所有的html文件都放置在一起,但是不方便。如果不同的app有相同的模板文件,django是不能分辨他们的,一个比较好的办法是将不同的模板放置在以app命名的文件夹中。

修改polls/templates/polls/index.html文件:

...{% if latest_question_list %}
{% else %}

No polls are available.

{% endif %}...

修改views文件

#_*_coding:utf-8_*_from django.shortcuts import HttpResponsefrom . import modelsfrom django.template import loaderdef index(request):    #倒排所有的question问题,只取前五个    latest_question_list = models.Question.objects.order_by("-pub_date")[:5]    #得到一个模板    temp = loader.get_template('polls/index.html')    #需要传入的内容,一个字典    context = {        "latest_qiestion_list":latest_question_list,    }    #返回    return HttpResponse(temp.render(context,request))...

A shortcut: render()

加载和渲染模板是非常频繁的工作,如果每次使用HttpResponse来返回,比较麻黄,因此django提供了一个叫做render()的捷径:

#_*_coding:utf-8_*_from django.shortcuts import HttpResponse,renderfrom . import modelsdef index(request):    #倒排所有的question问题,只取前五个    latest_question_list = models.Question.objects.order_by("-pub_date")[:5]    #返回    return render(request,"polls/index.html",{        "latest_question_list":latest_question_list,    })...

这样就不用导入loader了。render() 函数的第一个参数是request,第二个参数是模板,第三个参数是一个字典,用于模板传入参数使用, 返回一个给定内容和渲染模板的 HttpResponse 对象。

4 Raising a 404 error

下面来处理下detail视图,显示问题内容,修改polls/views.py文件:

...def detail(request,question_id):    try:        question = models.Question.objects.get(pk=question_id)    except models.Question.DoesNotExist:        raise Http404("Question does not exist")    return render(request,"polls/detail.html",{        "question":question    })...

修改polls/templates/polls/detail.html文件,如下:

{
{ question }}

A shortcut: get_object_or_404()

我们经常get一个对象数据,如果不存在就产生一个HTTP404,django提供了一个快捷方式:

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

Philosophy :

为什么我们使用get_object_or_404() 或者Http404 来代替ObjectDoesNotExist 呢?

因为我们需要联系models层和views层,django的一个重要设计理念就是维持松耦合,一些controlled 耦合 在django.shortcuts模块中介绍。

还有一个get_list_or_404() 函数,对应的filter(),而get_object_or_404() 对应的是get()。

5 使用模板系统(template)

回到detail()视图,我们修改一下detail.html文件:

{
{ question.question_text }}

    {#question.choice_set.all:全部choice#}{% for choice in question.choice_set.all %}{# 显示choice的内容:#}
  • {
    { choice.choice_text }}
  • {% endfor %}

通过“.”来获取question表对应的列,如question.question_text获取了question的内容;同样也能使用for进行循环,注意格式。

6 删除模板中url的硬编码

还记得index.html中的:

  • {
    { question.question_text }}
  • 我们给他改成:

  • {
    { question.question_text }}
  • 其实他是通过一个{% url %} 的template tag来实现调用的,详细请参考tempalte tag。

    那么如果哪天我需要修改url的时候,如:

    url(r'^specifics/(?P
    [0-9]+)/$', views.detail, name='detail'),

    就不需要再调整模板中的index.html文件。

    7 url的命名

    在我们的例子中只有一个app就是polls,但是在真实的django中,我们会有五个、十个甚至更多的app,怎么区分它们的url名字呢?比如说bolg和polls都有detail视图,那么使用{% url %}如何区分不同的app,方法就是在url文件中增加一行app_name = 'polls'

    from django.conf.urls import urlfrom . import viewsapp_name = "polls"  #增加此行urlpatterns = [    url(r'^$',views.index,name="index"),    url(r'^(?P
    [0-9]+)/$',views.detail,name="detail"), url(r'^(?P
    [0-9]+)/results/$',views.results,name="results"), url(r'^(?P
    [0-9]+)/vote/$',views.vote,name="vote"),]

    原来调用的时候:

  • {
    { question.question_text }}
  • 现在这样:polls:detail

  • {
    { question.question_text }}
  • 未完待续。

    转载于:https://www.cnblogs.com/felo/p/5561779.html

    你可能感兴趣的文章
    基于iSCSI的SQL Server 2012群集测试(一)--SQL群集安装
    查看>>
    list 容器 排序函数.xml
    查看>>
    存储开头结尾使用begin tran,rollback tran作用?
    查看>>
    Activity启动过程中获取组件宽高的五种方式
    查看>>
    java导出Excel表格简单的方法
    查看>>
    SQLite数据库简介
    查看>>
    利用堆实现堆排序&amp;优先队列
    查看>>
    Mono源码学习笔记:Console类(四)
    查看>>
    Android学习路线(十二)Activity生命周期——启动一个Activity
    查看>>
    《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇03:暂停游戏》
    查看>>
    CPU,寄存器,一缓二缓.... RAM ROM 外部存储器等简介
    查看>>
    windows下编译FreeSwitch
    查看>>
    git .gitignore 文件不起作用
    查看>>
    Alan Turing的纪录片观后感
    查看>>
    c#自定义控件中的事件处理
    查看>>
    App.config自定义节点读取
    查看>>
    unity3d根据手机串号和二维码做正版验证
    查看>>
    二十六、Android WebView缓存
    查看>>
    django Models 常用的字段和参数
    查看>>
    linux -- 嵌入式linux下wifi无线网卡驱动
    查看>>