Django views

编写你的第一个Django应用程序,第3部分¶
本教程从教程2停止的地方开始。我们将继续使用Web-poll应用程序,并将专注于创建公共界面 - “视图”。

概述¶
视图是Django应用程序中Web页面的“类型”,通常用于特定功能并具有特定模板。例如,在博客应用程序中,您可能具有以下视图:

博客主页 - 显示最新的几个条目。
条目“详细信息”页面 - 单个条目的永久链接页面。
基于年份的存档页面 - 显示给定年份中包含条目的所有月份。
基于月份的存档页面 - 显示给定月份中包含条目的所有日期。
基于日期的存档页面 - 显示给定日期内的所有条目。
评论操作 - 处理向给定条目发布评论。
在我们的民意调查申请中,我们将有以下四种观点:

问题“索引”页面 - 显示最新的几个问题。
问题“详细信息”页面 - 显示问题文本,没有结果,但有一个表单可以投票。
问题“结果”页面 - 显示特定问题的结果。
投票行动 - 处理特定问题中特定选择的投票。
在Django中,网页和其他内容由视图提供。每个视图都由一个简单的Python函数(或基于类的视图的方法)表示。Django将通过检查所请求的URL(确切地说,是域名后面的URL部分)来选择视图。

现在,在网络上你可能遇到过诸如“ME2 / Sites / dirmod.asp?sid =&type = gen&mod = Core + Pages&gid = A6CD4967199A42D9B65B1B”这样的美女。您会很高兴地知道Django允许我们提供更优雅的 URL模式。

URL模式只是URL的一般形式 - 例如: /newsarchive///。

为了从URL到视图,Django使用所谓的“URLconfs”。URLconf将URL模式映射到视图。

本教程提供了使用URLconf的基本说明,您可以参考URL调度程序以获取更多信息。

写更多视图¶
现在让我们再添加一些视图polls/views.py。这些观点略有不同,因为他们提出了一个论点:

民调/的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通过添加以下path()调用将这些新视图连接到模块中 :

民调/的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() 方法并显示您在URL中提供的任何ID。尝试“/ polls / 34 / results /”和“/ polls / 34 / vote /” - 这些将显示占位符结果和投票页面。

当有人从你的网站请求一个页面 - 比如“/ polls / 34 /”时,Django将加载mysite.urlsPython模块,因为它被ROOT_URLCONF设置指向 。它找到名为的变量urlpatterns 并按顺序遍历模式。找到匹配后’polls/’,它会剥离匹配的文本(“polls/”)并将剩余的文本 - “34/”- 发送到’polls.urls’URLconf以进行进一步处理。它匹配’int:question_id/’,导致调用detail()视图,如下所示:

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

.html除非您愿意,否则无需添加URL cruft ,在这种情况下,您可以执行以下操作:

path(‘polls/latest.html’, views.index),
但是,不要这样做。这太傻了。

写出实际做某事的视图¶
每个视图负责执行以下两项操作之一:返回HttpResponse包含所请求页面内容的 对象,或者引发异常,例如Http404。剩下的由你决定。

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

所有Django都想要的是HttpResponse。或者例外。

因为它很方便,所以让我们使用Django自己的数据库API,我们在教程2中介绍了它。这是一个新index() 视图,它根据发布日期显示系统中最新的5个轮询问题,以逗号分隔:

民调/的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

但是这里存在一个问题:页面的设计在视图中是硬编码的。如果要更改页面的外观,则必须编辑此Python代码。因此,让我们使用Django的模板系统,通过创建视图可以使用的模板将设计与Python分离。

首先,创建目录中调用templates的polls目录。Django会在那里寻找模板。

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

在templates刚刚创建的目录中,创建另一个名为的目录polls,并在其中创建一个名为的文件 index.html。换句话说,您的模板应该是 polls/templates/polls/index.html。由于app_directories 模板加载器的工作方式如上所述,您可以简单地在Django中引用此模板polls/index.html。

模板命名空间

现在我们可以直接放入我们的模板 polls/templates(而不是创建另一个polls子目录),但实际上这是一个坏主意。Django将选择它找到的第一个名称匹配的模板,如果你在不同的应用程序中有一个同名的模板,Django将无法区分它们。我们需要能够将Django指向正确的,并且确保这一点的最简单方法是通过命名它们。也就是说,将这些模板放在为应用程序本身命名的另一个目录中。

将以下代码放在该模板中:

民调/模板/调查/ index.html的¶
{% if latest_question_list %}


{% else %}

No polls are available.


{% endif %}
现在让我们更新我们的index视图polls/views.py以使用模板:

民调/的views.py ¶
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 /”来加载页面,您应该看到一个项目符号列表,其中包含教程2中的“What is up”问题。该链接指向问题的详细信息页面。

快捷方式:¶render()
加载模板,填充上下文并返回HttpResponse带有渲染模板结果的对象是一种非常常见的习惯用法 。Django提供了一个捷径。这是完整的index()视图,重写:

民调/的views.py ¶
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(你想保留HttpResponse,如果你仍然有存根方法detail, results和vote)。

该render()函数将请求对象作为其第一个参数,将模板名称作为其第二个参数,将字典作为其可选的第三个参数。它返回使用HttpResponse 给定上下文呈现的给定模板的对象。

引发404错误¶
现在,让我们解决问题详细信息视图 - 显示给定民意调查的问题文本的页面。这是观点:

民调/的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})
这里的新概念:Http404如果不存在具有请求ID的问题,则视图会引发异常。

稍后我们将讨论您可以在该polls/detail.html模板中添加的内容,但是如果您希望快速获得上述示例,则只需包含以下内容的文件:

民调/模板/调查/ detail.html ¶
{{ question }}
会让你现在开始。

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

民调/的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.shortcuts模块中引入了一些受控耦合。

还有一个get_list_or_404()函数,它的工作方式与get_object_or_404()- 除了使用 filter()而不是 get()。Http404如果列表为空,它会引发 。

使用模板系统¶
返回detail()我们的民意调查应用程序的视图。给定上下文变量question,这是polls/detail.html模板的外观:

民调/模板/调查/ detail.html ¶

{{ question.question_text }}

  • {% for choice in question.choice_set.all %}
  • {{ choice.choice_text }}
  • {% endfor %}
模板系统使用点查找语法来访问变量属性。在示例中,首先Django对该对象进行字典查找。如果失败了,它会尝试进行属性查找 - 在这种情况下可以正常工作。如果属性查找失败,它将尝试列表索引查找。{{ question.question_text }}question

方法调用在循环中发生: 被解释为Python代码 ,它返回一个可迭代的对象,适合在标记中使用。{% for %}question.choice_set.allquestion.choice_set.all()Choice{% for %}

有关模板的更多信息,请参阅模板指南。

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

  • {{ question.question_text }}
  • 这种硬编码,紧密耦合方法的问题在于,在具有大量模板的项目上更改URL变得具有挑战性。但是,由于您path()在polls.urls模块中的函数中定义了name参数,因此可以使用模板标记来消除对URL配置中定义的特定URL路径的依赖:{% url %}
  • {{ question.question_text }}
  • 这种方式的工作方式是查找polls.urls模块中指定的URL定义 。您可以在下面确切地看到“详细信息”的URL名称的位置:

    the ‘name’ value as called by the {% url %} template tag

    path(‘int:question_id/’, views.detail, name=‘detail’),

    如果您想将民意调查详细信息视图的URL更改为其他内容,可能polls/specifics/12/会更改为在模板(或模板)中执行此操作,您可以将其更改为polls/urls.py:

    added the word ‘specifics’

    path(‘specifics/int:question_id/’, views.detail, name=‘detail’),

    命名空间URL名称¶
    教程项目只有一个应用程序polls。在真正的Django项目中,可能有五个,十个,二十个应用程序或更多。Django如何区分它们之间的URL名称?例如,polls应用程序有一个detail 视图,因此同一项目中的应用程序可能适用于博客。如何使Django知道在使用模板标签时为url创建哪个应用视图 ?{% url %}

    答案是为URLconf添加名称空间。在polls/urls.py 文件中,继续并添加一个app_name以设置应用程序命名空间:

    民调/的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模板:

    民调/模板/调查/ index.html的¶

  • {{ question.question_text }}
  • 指向命名空间详细信息视图:

    民调/模板/调查/ index.html的¶

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值