zoukankan      html  css  js  c++  java
  • 实战Django:官方实例Part3

    前面两个部分我们介绍了投票应用的框架和后台管理部分。接下来舍得要介绍这个应用面向用户的界面。

    这里我们要引入一个新的概念,“视图”。在Django中,视图是一根连接模型和模板的纽带,它决定哪些数据要呈现给用户。

    来看一下Django的这几个核心概念:

    • 模型:负责和数据库打交道,把数据传入、传出给数据库;
    • 模板:负责最终显示给用户的页面的显示方式;
    • 视图:将模型和模板连接在一起,它决定了哪些数据要显示给用户;
    • 链接:Django中有一项url配置,它充当着整个程序的入口,用户在地址栏中输入地址时,由链接模块去决定将这个地址分发到哪里;

    带着这些概念,我们来写下本例中的第一个视图:

    14.编写视图


    编辑polls/views.py 文件,添加下面的内容:

    polls/views.py

    from django.http import HttpResponse
    
    
    def index(request):
        return HttpResponse("嗨,哥们,你现在正在访问的是投票应用的首页.")

    这可能是Django中最简单的视图了。要想让视图的内容最终呈现给用户,我们还需要将这个视图关联(术语叫映射)到URL文件中。

    现在我们需要在polls文件夹下创建一个叫url.py的文件,创建完后,你的应用文件夹应该是下面这个样子:

    polls/
        __init__.py
        admin.py
        models.py
        tests.py
        urls.py
        views.py

    编辑polls/urls.py 文件,加入下面这些代码:

    polls/urls.py

    from django.conf.urls import patterns, url
    
    from polls import views
    
    urlpatterns = patterns('',
        url(r'^$', views.index, name='index'),
    )

    此时,从应用到用户那条路还没打通,我们还需要在站点的urls.py中把链接指向刚编辑完的urls.py。

    编辑mysite/urls.py 文件,让它变成下面这样:

    mysite/urls.py

    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    
    urlpatterns = patterns('',
        url(r'^polls/', include('polls.urls')),
        url(r'^admin/', include(admin.site.urls)),
    )

    注意观察第四行,它把我们的polls/urls.py关联到了mysite/urls.py 中。

    url()中的第一个参数,如”r'^polls/'”,这个叫正则表达式。关于正则表达式的内容,童鞋们可以参阅一些相关的书籍或文章,比如《精通正则表达式》或舍得写的正则表达式实战教程。

    上面这个操作做完后,我们打开浏览器,在地址栏中输入:

    可以看到我们的工作成果:

    22

    我们再来添加一些视图,编辑polls/views.py 文件,添加下面的内容:

    polls/views.py

    def detail(request, question_id):
        return HttpResponse("你正在查看的是问题%s." % question_id)
    
    def results(request, question_id):
        response = "你正在查看的是问题%s的投票结果."
        return HttpResponse(response % question_id)
    
    def vote(request, question_id):
        return HttpResponse("你正在为问题%s投票." % question_id)

    现在我们只需要编辑polls/urls.py 文件就可以让视图生效了:

    polls/urls.py

    from django.conf.urls import patterns, url
    
    from polls import views
    
    urlpatterns = patterns('',
        # 如: /polls/
        url(r'^$', views.index, name='index'),
        # 如: /polls/5/
        url(r'^(?P<question_id>d+)/$', views.detail, name='detail'),
        # 如: /polls/5/results/
        url(r'^(?P<question_id>d+)/results/$', views.results, name='results'),
        # 如: /polls/5/vote/
        url(r'^(?P<question_id>d+)/vote/$', views.vote, name='vote'),
    )

    转到浏览器界面,分别用下面这些链接去访问一下:

    http://127.0.0.1:8000/polls/1/
    http://127.0.0.1:8000/polls/1/result
    http://127.0.0.1:8000/polls/1/vote

    我们来分析一下Django的处理流程。在本例中,当用户访问到http://127.0.0.1:8000/polls/1/results这样的链接时:

    • Django会先在mysite/urls.py 中找“^poll/”;
    • 找到后,Django会去掉“poll/”,把剩下的“1/results”发到polls/urls.py 中继续处理;
    • 在polls/urls.py 发现能匹配到“r'^(?P<question_id>d+)/results/$'”,最终显示polls/views.py中的results视图;

    15.进阶版视图


    前面的视图仅仅是让大家熟悉Django的基本处理流程。现在,我们来进入实战状态,编写真正有用的视图。

    编辑polls/views.py 文件,让它变成下面这样:

    polls/views.py

    from django.http import HttpResponse
    
    from polls.models import Question
    
    
    def index(request):
        latest_question_list = Question.objects.order_by('-pub_date')[:5]
        output = ', '.join([p.question_text for p in latest_question_list])
        return HttpResponse(output)
    
    # 下面的那些视图暂时留着别删 (detail, results, vote)

    看下效果:

    23

    数据库里的内容显示出来了。

    但这种做法并不可取。因为我们把控制页面显示效果的编码放在.py文件中,这样的方式我们称之为”硬编码“,它意味着以后每一次要改动页面效果,都需要修改这个.py文件,显然极为不便。

    正确的做法是,把页面显示相关的部分交给模板系统来处理。

    首先,请在polls文件夹下建立templates文件夹,Django会自动搜索到它。

    在templates文件夹中建立一个文件夹,叫polls,然后在这个polls文件夹下新建一个index.html文件,这是我们的投票应用的首页模板。这个模板的路径应该是:

    polls/templates/polls/index.html

    把下面这些代码添加到index.html中(Html文件用文本编辑器来完成就可以了,舍得推荐使用emeditor):

    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 文件,改成这样:

    polls/views.py

    from django.http import HttpResponse
    from django.template import RequestContext, loader
    
    from polls.models import Question
    
    
    def index(request):
        latest_question_list = Question.objects.order_by('-pub_date')[:5]
        template = loader.get_template('polls/index.html')
        context = RequestContext(request, {
            'latest_question_list': latest_question_list,
        })
        return HttpResponse(template.render(context))

    在上面这段代码中,我们先载入“polls/index.html”这个模板,传递给它一个叫context的对象,这个context包含了我们想要显示的数据。

    来看下效果:

    24

    “What's Up?”变成了链接的形式,链接指向了投票的内容页。

    上面这样的写法,在Django中有更便捷的方式,我们来修改polls/views.py 文件:

    polls/views.py

    from django.shortcuts import render
    
    from polls.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)

    这样的代码更加简洁。而且更易于阅读。

    render()函数使用request作为第一个参数,模板名作为第二个参数,把context这个字典类型数据作为第三个参数。它会用数据用模板渲染好,呈现到用户面前。

    16.处理404错误


    现在,让我们来着手设计投票内容页。

    编辑polls/views.py 文件:

    polls/views.py

    from django.http import Http404
    from django.shortcuts import render
    
    from polls.models import Question
    # ...
    def detail(request, question_id):
        try:
            question = Question.objects.get(pk=question_id)
        except Question.DoesNotExist:
            raise Http404
        return render(request, 'polls/detail.html', {'question': question})

    这里引入了一个新的概念,当用户访问的投票项不存在时,视图会抛出一个Http404异常来通知用户。

    给上面这个视图配上对应的模板,建立detail.html文件 ,并添加以下内容:

    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>

    刚才那个视图,Django里有更为便捷的写法,编辑polls/views.py 文件,把它改成这样:

    polls/views.py

    from django.shortcuts import get_object_or_404, render
    
    from polls.models import Question
    # ...
    def detail(request, question_id):
        question = get_object_or_404(Question, pk=question_id)
        return render(request, 'polls/detail.html', {'question': question})

    现在,点击刚才浏览器中的那个“What's Up?”链接,我们就可以看到象下面这样的页面:

    25

    在Django的模板系统中,我们要注意的是两类符号,一类是双大括号,如:{{question.question_text }};另一类是{% 的形式,如{% for choice in question.choice_set.all %}。前者仅仅是一个值,后者则相当于一段程序。

    在本例中,{% for %} 代表了一个for循环,question.choice_set.all包含了这个投票的所有选项,用一个for循环就可以把它全部显示出来。

    17.移除模板中的硬编码


    在我们刚才的模板中,也存在着我们前面说过的硬编码问题。

    像下面这样的代码:

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

    这里的”/polls/{{ question.id }}/“采用常量的方式写入链接,一旦以后有变动,要修改链接,可能会产生大量的额外工作量。

    好在我们可以解决这个问题。上面的这段代码我们可以写为:

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

    当此模板被呈现的时候,Django会自动到你定义的urls.py文件中去寻找”detail”这个名称,它会在polls/urls.py中找到:

    ...
    # 这里的'name'值就是{% url %} 模板标签调用的地方。
    url(r'^(?P<question_id>d+)/$', views.detail, name='detail'),
    ...

    这样,你要修改链接,比如把它改0“成polls/specifics/12/”,不用去逐个修改模板,只要改动polls/urls.py就可以了,如:

    ...
    # 链接中加入'specifics'
    url(r'^specifics/(?P<question_id>d+)/$', views.detail, name='detail'),
    ...

    18.创建URL命名空间


    我们这个例子只有一个应用,而在真实的项目中,往往五个、十个、二十个甚至更多的应用。在这种时候,url名称会不会被搞混掉?举个例子,我们这个polls应用有个叫detail的视图,某一天,在同一项目下增加了一个blog的应用,它也有一个detail视图,怎么来区分呢?

    这就是命名空间存在的意义。

    编辑mysite/urls.py文件,增加命名空间的属性:

    mysite/urls.py:

    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    
    urlpatterns = patterns('',
        url(r'^polls/', include('polls.urls', namespace="polls")),
        url(r'^admin/', include(admin.site.urls)),
    )

    修改模板文件polls/index.html,把它从:

    polls/templates/polls/index.html

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

    改为:

    polls/templates/polls/index.html

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

    这样,以后即便应用再多,也不会起冲突了。

    【未完待续】

    本文版权归舍得学苑所有,欢迎转载,转载请注明作者和出处。谢谢!
    作者:舍得
    首发:舍得学苑@博客园

  • 相关阅读:
    让所有IE支持HTML5的解决方案
    MVC3实现多个按钮提交
    水平垂直居中
    模块化开发之sea.js实现原理总结
    express常见获取参数的方法
    使用nodemon提高nodejs调试效率
    Vue2 实践揭秘 错误列表
    全局安装 Vue cli3 和 继续使用 Vue-cli2.x
    使用VUECLI3
    npm ERR! code Z_BUF_ERROR
  • 原文地址:https://www.cnblogs.com/emagic/p/4148777.html
Copyright © 2011-2022 走看看