Django基础(4)编写前端视图

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hy245120020/article/details/49508177

视图

Django使用叫做‘URLconfs’的配置来为URL匹配视图。 一个URLconf负责将URL模式匹配(使用正则表达式)到视图。
在我们的投票应用中,将有以下四个视图:
Question首页 —— 显示最新发布的几个Question。
Question“详细”页面 —— 显示单个Question的具体内容,不显示该议题的当前投票结果,而是提供一个投票的表单。
Question“结果”页面 —— 显示特定的Question的投票结果。
投票功能 —— 处理对Question中Choice的投票。

编写视图

目录视图:

这里写图片描述

在应用的模板目录下(polls/templates)而不是项目模板目录下(templates),主要是为了重用性。

编写:polls/views.py

#!usr/bin/env python
# coding=utf-8
from django.shortcuts import render, get_object_or_404

# Create your views here.
from django.http import HttpResponse, Http404
from django.template import RequestContext, 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 = RequestContext(request, {
    #     'latest_question_list': latest_question_list
    # })
    # return HttpResponse(template.render(context))

    # render快捷方式
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

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})
    # 模型层和视图层分开,自动处理异常
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

编写:polls/urls.py

from django.conf.urls import url
from . import views
# 正则表达式
# 字符        含义
# ^         行首
# $            行尾
# \d            任意数字
# \s            任意空白字符
# \w            [A-Za-z0-9]
# *         零个或多个
# +         一个或多个
# ?         零个或一个
# {2,}      两个以上
urlpatterns = [
    # ex: /polls/
    url(r'^$', views.index, name='index'),
    # ex: /polls/5/
    url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
    # ex: /polls/5/results/
    url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
    # ex: /polls/5/vote/
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

在这里解释一下def url(regex, view, kwargs=None, name=None, prefix=”)方法的四个参数:

regex:是一种用来匹配字符串中模式的语法,在这里是URL模式。 Django从第一个正则表达式开始,依次将请求的URL与每个正则表达式进行匹配,直到找到匹配的那个为止。
请注意,这些正则表达式不会检索URL中GET和POST的参数以及域名。
例如,对于http://www.example.com/myapp/请求,URLconf 将查找myapp/。
对于http://www.example.com/myapp/?page=3请求,URLconf 也将查找myapp/。
最后,性能方面的一个注意点:这些正则表达式会在URLconf模块第一次载入的时候被编译。 它们超级快(只要这些正则表达式不像上面提醒的那样过于复杂)。

view:当Django找到一个匹配的正则表达式时,它就会调用给定的视图函数,并将HttpRequest对象作为第一个参数,从正则表达式中“捕获”的所有值作为其他参数。如果正则表达式使用简单的捕获方式,值将作为位置参数传递; 如果使用命名的捕获方式,值将作为关键字参数传递。

kwargs:任何关键字参数都可以以字典形式传递给目标视图。

name:命名你的URL可以让你在Django的其它地方,尤其是模板中,通过名称来明确地引用它。 这个强大的特性可以使你仅仅修改一个文件就可以改变全局的URL模式。

上面我们已经在应用中添加了url匹配,我们要把整个应用添加到当前的工程中,编写myside/urls.py:

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^polls/', include('polls.urls', namespace="polls")),
]

在这里我们添加polls应用的匹配路径和命名空间,命名空间的作用主要是为了识别不同应用中相同的路径名称。例如,polls 应用具有一个detail 视图,相同项目中的博客应用可能也有这样一个视图。当使用模板标签{% url %}时,人们该如何做才能使得Django知道为一个URL创建哪个应用的视图?这个时候就需要指定命名空间。
编写templates/polls/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
{% if latest_question_list %}
<ul>
    {% for question in latest_question_list %}
    <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
</body>
</html>

编写templates/polls/detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
<ul>
    {% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
    {% endfor %}
</ul>
</body>
</html>

在这里可以看到index.html中的<a href="{% url 'polls:detail' question.id %}">是指定命名空间polls下的detail页面,避免发生多个应用之间重复。而detail是polls/urls.py中配置的name属性,主要的作用是为了在页面修改url的时候我只需要修改urls.py中的正则匹配就可以修改全部的url。

编写一个简单的表单

编写的投票详细页面的模板(“polls/detail.html”),让它包含一个HTML 元素polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

修改polls/urls.py

url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),

修改polls/views.py

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse

from .models import Choice, Question
# ...
def vote(request, question_id):
    p = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = p.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': p,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))

编写view结果页polls/views.py

def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

编写polls/results.html

<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

现在,在你的浏览器中访问/polls/1/然后为Question投票。你应该看到一个投票结果页面,并且在你每次投票之后都会更新。 如果你提交时没有选择任何Choice,你应该看到错误信息。

我们设置表单的action为{% url ‘polls:vote’ question.id %},并设置 method=”post”。使用method=”post”(与其相对的是method=”get”)是非常重要的,因为这个提交表单的行为会改变服务器端的数据。 无论何时,当你需要创建一个改变服务器端数据的表单时,请使用 method=”post”。这不是Django的特定技巧;这是优秀的网站开发实践。

你应该在成功处理POST数据后总是返回一个HttpResponseRedirect。 这不是Django的特定技巧; 这是那些优秀网站在开发实践中形成的共识。

我们创建一个POST表单(它具有修改数据的作用),所以我们需要小心跨站点请求伪造。 Django已经拥有一个用来防御它的非常容易使用的系统。 简而言之,所有针对内部URL的POST表单都应该使用{% csrf_token %}模板标签。

编写视图的步骤总结:
1.编写polls/views.py
2.编写polls/urls.py
3.编写myside/urls.py
4编写html显示页面

展开阅读全文

没有更多推荐了,返回首页