(3) django官方教程---视图views

views是django应用程序中的一类web页面,服务于特定的功能并且具有特定的模板。在此,我们将建立4个视图:index page , detail page , results page , vote action.

1.编写基本的view与url

django通过检测请求的url来选择view,这是通过URLconfs实现的。URLconfs将URL映射到view.
添加一些views到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)

添加如下path(),将views写到polls.urls模块中。

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如:/polls/34/ , /polls/34/results/ , /polls/34/vote等。这将会运行相应的view方法并展示一个包含数字的字符串。

过程解释:
当某人请求/polls/34时,django首先会根据ROOT_URLCONF设置项加载mysite.urls模块。它发现了一个名为urlpatterns的变量,并按顺序遍历它。当发现匹配项polls/时,他会截掉匹配的文本(“polls/”),将剩下的文本(“34/”)发送到polls.urls这个URLconfs做进一步处理。最后它匹配到’< int:question_id >’,便调用detail() 这个view:

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

question_id=34来自< int:question_id >,使用尖括号捕获URL中的部分,将其转换为int类型后以关键字参数question_id发送给view方法。

每个视图负责两件事之一:返回包含请求页面内容的HttpResponse对象,或者引发如Http404的异常。它可以做你要想的任何事,如读数据库记录,使用模板,生成PDF文件,输出XML等等。但必须返回HttpResponse或一个异常

让我们丰富view的行为,修改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)

这里有一个问题:页面设计被硬编码在视图中。这样当要修改页面呈现时,必须修改python代码。我们可以使用django的模板系统通过创建一个视图使用的模板,将页面设计与python分离。
首先在polls下创建templates目录
TEMPLATE设置项描述了django是如何加载和渲染模板的。默认设置文件配置了一个django templates后端,他的APP_DIRS选项被设为True.按照约定,djangoTemplates会在每个INSTALLED_APP中寻找templates子目录。

模板命名空间

在刚刚创建的templates目录下再创建polls/index.html,即polls/templates/polls/index.html,由于之前的原因,指向该模板时只需声明polls/index.html。如果在不同应用程序下的templates目录下存在同样的模板,django是不能区分他们的。我们可以通过模板命名空间(将模板放在templates目录下与应用程序同名的子目录中)解决该问题。
编辑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

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的模板并传递给他一个context , context是一个字典,会将模板变量映射为python对象。

render快捷方式

这是一种相当常见的习惯:加载一个模板,填充一个context,并返回包含渲染模板的HttpResponse对象。为此django提供了一个快捷方式。如下:

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)

参考上述方式,修改所有其他view

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

使用快捷方式取代:get() 然后抛出 Http404
即用 question = get_object_or_404(Question, pk=question_id)取代以上try…except部分。其第一个参数为model对象,其他参数都将传递给get方法。不在更高水品或让模型API引起Http404的错误,是为了降低耦合度。类似的方法有get_list_or_404(),他使用filter方法
使用模板系统

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

模板系统使用dot-lookup语法访问变量属性。在例子{{ question.question_text }}中,django首先对question进行字典查找。失败后,进行属性查找,这里发现了结果。如果属性查找失败,会进行list-index查找。

在for循环中发生了方法调用,question.choice_set.all被解释为python代码question.choice_set.all()。他返回一个可迭代对象,然后被for这个tag使用。

移除模板中的硬编码

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

这个硬编码、紧耦合带来了这样的问题:当一个项目有很多模板时,改变其中的URLconf是一个大的挑战。
我们之前在polls.urls模块中的path()方法中定义了name参数,我们可以使用{% url %}模板标签消除对url配置文件中特定url路径的依赖。

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

之后我们可以在URLconf文件中修改url路径,而不需要动模板文件。
命名空间的url名字
在具有很多app的项目中,可能在URLconf文件中的path()方法中指定了同样的name参数。为了在{% url %}中区分他们,我们可以使用url命名空间
在polls/urls.py文件中的urlpatterns行之前添加app_name=’polls’即可实现。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值