Django 2.1.6.学习初级篇(3)

目录

No. 1 开始创造更多views

No. 2  编写实际操作的views

No.3 引发404错误

No.4 正确使用模板系统

No.5 在模板中删除硬编码的url


本教程从Django 2.1.6.学习初级篇(2)停止的地方开始。我们继续web轮询应用程序,并将重点创建公共接口—“views”。

在Django中,web页面和其他内容由views交付。每个视图都由一个简单的Python函数(在基于类的视图中是一个方法)表示。Django将通过检查请求的URL(准确地说,是域名后面的URL部分)来选择视图。

No. 1 开始创造更多views

我们都知道,游戏不可能就一张图让你玩到底,不然怎么让你氪金呢。

当然,一个polls应用也一样,首先先了解需求,这个应用要什么界面

一个展示问题的界面,views上设置为detail函数

一个显示问题投票结果的界面,views上设置为results函数

一个展示让你投票的界面,views上设置为vote函数

现在让我们向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)

看一下return结果大概就可以猜出每个views代表界面意思,虽然现在看起来return效果一样,但是后面肯定会改的吗,你懂了?行,你来,你来。

配置了views,当然要配置url重定向呀,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'),
]

URL匹配规则大家应该了解了。比如你在网站输入http://127.0.0.1:8000/polls/3,那么首先在mysite/urls找/polls进行匹配,符合要求的第一个在根据设置跳转到polls/urls.py匹配,在'polls/'找到匹配后,它将删除匹配的文本("polls/"),并将其余文本(" 3/")发送到'polls/'。用于进一步处理的url的URLconf。在这里,它匹配'<int:question_id>/',结果调用detail()视图如下:

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

question_id=3部分来自<int:question_id>。使用尖括号“捕获”URL的一部分,并将其作为关键字参数发送给视图函数。字符串的:question_id>部分定义了将用于标识匹配模式的名称,<int: part是一个转换器,用于确定哪些模式应该匹配URL路径的这一部分。

当然,你也可以不传参数,直接按死polls/urls.py中的视图重定向,像这样:

path('polls/latest.html', views.index)

但是,最好不要这么做,有点捞。

 

No. 2  编写实际操作的views

每个视图负责做两件事中的一件:返回包含请求页面内容的HttpResponse对象,或者引发Http404等异常。剩下的由你决定。

视图可以从数据库中读取记录,也可以不读取。它可以使用Django这样的模板系统,也可以不使用第三方Python模板系统。它可以生成PDF文件、输出XML、动态创建ZIP文件,任何您想要的东西,使用任何您想要的Python库。

页面的设计在视图中是硬编码的。如果您想更改页面的外观,就必须编辑这段Python代码。因此,让我们使用Django的模板系统通过创建视图可以使用的模板来将设计与Python分离开来。

Django提供了一个快捷方式。更改polls/views中的index():

from django.shortcuts import render

from .models import Question


def index(request):
    # 返回返回最后五个已发布的问题
    latest_question_list = Question.objects.order_by('-pub_date')[:5] 
    # '-pub_data'中表示按照pub_data的发布时间逆序查找,'-'为逆序查找,
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

render()函数的第一个参数是request对象,第二个参数是模板名,第三个参数是字典。它返回给定上下文呈现的给定模板的HttpResponse对象。

值得注意的是Question.objects,让我们使用Django自己的数据库API,这在初级篇2中已经介绍过了。有些人会出现波浪线提示错误,那你就这样做,在polls/models.py的Qusetion类中加一行,至于原因,百度呀:

objects = models.Manager()

 

然后,在poll目录中创建一个名为templates的目录。Django将在其中寻找模板。项目的模板设置描述Django将如何加载和呈现模板。默认设置文件配置一个DjangoTemplates后端,其APP_DIRS选项设置为True。按照惯例,DjangoTemplates在每个INSTALLED_APPS中查找“templates”子目录。

现在,我们可以将模板直接放入poll /templates中(而不是创建另一个poll子目录),但这实际上是一个坏主意(对大佬来说)。Django将选择它找到的第一个名称匹配的模板,如果在不同的应用程序中有同名的模板,Django将无法区分它们。我们需要能够将Django指向正确的位置,确保这一点的最简单方法是对它们进行命名空间。也就是说,将这些模板放在另一个以应用程序本身命名的目录中。,总的来说,这样方便你polls程序迁移到一个django框架。

在模板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/index的模板。并传递一个上下文。上下文是将模板变量名映射到Python对象的字典。

通过将浏览器指向“/polls/”加载页面,您将看到一个项目符号列表,其中包含初级篇2中的“What 's up”问题。链接指向问题的详细页面。

No.3 引发404错误

现在,让我们处理问题细节视图——显示给定投票的问题文本的页面视图,polls/views.py:

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

这里的新概念是:如果具有所请求的ID的问题不存在,视图将引发Http404异常。

我们将讨论你可以在polls/detail.html中加入什么模板,但如果你想快速得到上述例子的工作,可以在一个只包含:

polls/templates/polls/detail.html

{{ question }}

如果对象不存在,则使用get()和引发Http404是非常常见的习惯用法。Django提供了一个快捷方式。这是detail()视图,重写如下:

polls/views.py

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_object_or_404()函数接受Django模型作为它的第一个参数和任意数量的关键字参数,并将这些参数传递给模型管理器的get()函数。如果对象不存在,它将引发Http404。

为什么我们使用帮助函数get_object_or_404()而不是在更高的级别上自动捕获ObjectDoesNotExist异常,或者让模型API引发Http404而不是ObjectDoesNotExist?因为这会把模型层和视图层结合起来。Django的首要设计目标之一是保持松散耦合。django中引入了一些控制耦合在django.shortcuts模块中。

No.4 正确使用模板系统

回到polls应用程序的detail()视图,创建的detail模板是这样的:

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对对象问题进行字典查找。如果做不到这一点,它将尝试属性查找——在本例中,这是有效的。

如果属性查找失败,它将尝试列表索引查找。

如在{% for %}循环中,question.choice_set.all(polls/models.py模型Question没有choice_set.all属性)被解释为Python代码question.choice_set.all()【polls/models.py模型Question继承models.Model,父类有这个choice_set.all()方法】,它返回一个可迭代的Choice对象,并且适合在{% for %}标记中使用。

模板更多知识将在中级篇讲到。

No.5 在模板中删除硬编码的url

记住,当我们在polls/index.html模板中写问题的链接时。链接部分硬编码如下:

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

通常网页有上百个链接,你如果修改你的网页链接,那index.html的链接都要改,很明显,这很麻烦。

但是,由于您在polls/urls.py中的path()函数中定义了name参数。URL模块,您可以通过使用{% URL %}模板标记来消除对URL配置中定义的特定URL路径的依赖:

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

这种方法(也可以说是反向解析url)的工作方式是查找 polls.urls模块中中指定的URL定。您可以看到“detail”的URL名称的确切定义如下:

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

这种方法的工作方式是查找detail中指定的URL定义。如果你想要将poll详情视图的URL更改为其他内容,比如poll /specific /12/而不是在模板中执行,你可以在polls/ urls .py中进行更改:

...
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...

你可以打开网页观察,结果一样,polls/index.html根本不需要改变。

教程项目只有一个应用程序,polls。在真正的Django项目中,可能有5个、10个、20个或更多的应用程序。Django如何区分它们之间的URL名称?例如,poll应用程序有一个详细视图,同一项目上的应用程序也可能有一个博客的详细视图。如何使Django在使用{% url %}模板标记时知道要为url创建哪个应用程序视图?

答案是在URLconf中添加名称空间。在polls/ urls.py文件,然后添加app_name来设置应用程序名称空间:

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>

当您熟悉编写视图时,请阅读Django 2.1.6.学习初级篇(4),了解简单的表单处理和通用视图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值