python 的web框架 django 的入门教程 3 网页(view)

本文是在 python 的web框架 django 的入门教程 2 数据库 上开始的。根据 django 官方教程 学习而来,内容也与其教程3配对。

下一章:python 的web框架 django 的入门教程 4 表单 

继续网上投票程序,这章关注的是建立接口View。

view在django 中是网页的一种类型,他有特定的功能和模板。

在我们的polls应用程序中,我们有以下四个视图:

Question“index”页面–显示最新的几个问题。
Question“detail”页面–显示问题文本,没有结果,但有一个投票表。
Question“result”页面–显示特定问题的结果。
polls行动–处理特定问题中特定选择的投票。

为了从URL到view,Django使用了“ URLconfs”。 URLconf将URL映射到view。

添加更多view

给polls/views.py文件,添加如下内容:

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模块需要给这些view建立关联,修改polls/urls.py

from django.urls import path

from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

现在浏览器里检查我们的成果。/polls/34/ 时运行detail ,也就是http://127.0.0.1:8000/polls/34/时,显示:

You're looking at question 34.

http://127.0.0.1:8000/polls/34/vote/ 时,显示 You're voting on question 34.

http://127.0.0.1:8000/polls/34/results/  时,显示 You're looking at the results of question 34.

原文教程这么说,但我开始显示404 错误。查看mysite\mysite\urls.py 文件。

 path('polls/', include('polls.urls')), 这一行被注释了,取消注释,才得到上面的结果。

过程说明

当请求网页比如:“/polls/34/” 的时候,首先到mysite\mysite\urls.py , 因为这里是ROOT_URLCONF,遍历变量urlpatterns /polls对应/polls,这样找到polls/urls.py,并把剩余参数34/传递给他。在polls/urls.py里遍历变量urlpatterns,匹配<int:question_id>/的就是views.detail,最后调用polls/views.py里的 detail()如下:

detail(request=<HttpRequest object>, question_id=34)

question_id=34 来自 <int:question_id>,int: 转化为int。

编写实际内容的view

每个view执行以下2项操作之一:返回包含所请求页面内容的HttpResponse对象,或引发诸如Http404之类的异常。 其余内容的取决于你的设计。

view可以从数据库中读取记录。 可以使用Django或者第三方Python模板。 可以使用所需的任何Python库生成PDF文件,输出XML,即时创建ZIP文件。

Django想要的只是HttpResponse或者一个异常响应。

我们这里使用Django自己的数据库API,在教程2中有了介绍。下面是index()的新view,它根据发布日期显示系统中最新的5个polls问题,并用逗号分隔。

修改前面的polls/views.py文件如下:

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)

# Leave the rest of the views (detail, results, vote) unchanged

保存,运行后我们只是显示一些文字。要有格式等需要编辑py文件很复杂。这里就引入模板,让形式和内容分离。

polls目录下建立一个目录 templates,然后templates下再建一个polls目录,最后文件是这样的路径: polls/templates/polls/index.html  。

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 部分内容如下:

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))

现在运行测试有格式了。

快捷函数 render()

加载模板,填充上下文并返回HttpResponse对象,这些操作太常见了,所有有个快捷函数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)

有了这个,不再需要loader 和HttpResponse,不过我们这里暂时需要,因为其他view 还用了他。

引发404错误

现在转到detail 这个view ,有错误时引发404 错误。

from django.http import Http404
from django.shortcuts import render

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

快捷函数:get_object_or_404()

对象不存在时,使用get()并引发Http404是一个常见的操作。 Django提供了一个快捷方式。 以下是改写的detail():

from django.shortcuts import get_object_or_404, render

from .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})

还有个类似的函数 get_list_or_404(),如果list 为空的时候,引发404。

对应detail()的模板文件 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%中使用 } 标签。

删除模板中的硬编码URL

当我们在polls / index.html模板中编写到question的链接时,该链接有部分硬编码,如下所示:

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

这种硬编码的问题在于,在有大量模板的项目上更改URL变得具有挑战性。 由于在polls.urls模块的path()函数中定义了名称参数,因此可以使用{%url%}模板标记来消除对url配置中定义的特定URL路径的依赖: 

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

它的工作方式是通过查询polls.urls模块中指定的URL定义。 可以在下面看到确切的网址名称“ detail”的定义:

...
# the 'name' value as called by the {% url %} template tag
path('<int:question_id>/', views.detail, name='detail'),
...

name 的值 detail 在{% url %} 中被替换

如果将polls detail 的URL更改为其他内容,例如,将其更改为polls/ specifics / 12 /之类的内容,而不是在一个或多个模板中进行更改,则可以在polls/urls.py中进行更改:

...
# 添加单词 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...

命名空间URL名称

教程项目只有一个应用程序,polls。 在实际的Django项目中,可能有五个,十个,二十个或更多应用程序。 Django如何区分它们之间的URL名称? 例如,polls应用程序具有详细信息视图,同一项目中的应用程序也可能具有博客视图。 如何做到这一点,以便Django在使用{%url%}模板标记时知道为该URL创建哪个应用视图?

答案是将名称空间添加到您的URLconf中。 在polls / urls.py文件中,添加一个app_name来设置应用程序名称空间:

app_name = 'polls'

polls / urls.py 文件内容是这样的:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

对应的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>

 原来的detail 变为 polls:detail了。

本章内容就到此为止。如果对view 比较有感觉了,可以进入下一章:python 的web框架 django 的入门教程 4 表单 

发布了131 篇原创文章 · 获赞 112 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/leon_zeng0/article/details/102908372