干巴爹兔的博客 干巴爹兔的博客
首页
  • 前端文章

    • JavaScript
    • HTML
    • Vue
  • 学习笔记

    • JavaScript教程
    • React学习笔记
    • Electron学习笔记
  • 开源项目

    • cloud-app-admin
    • 下班了吗Vscode插件
    • Subversion变更单插件
  • Server

    • Django
  • 学习笔记

    • MySQL学习笔记
  • 运维

    • 服务器部署
    • Linux
  • 日常学习

    • 学习方法
关于
收藏
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

干巴爹兔

卑微的前端打工人
首页
  • 前端文章

    • JavaScript
    • HTML
    • Vue
  • 学习笔记

    • JavaScript教程
    • React学习笔记
    • Electron学习笔记
  • 开源项目

    • cloud-app-admin
    • 下班了吗Vscode插件
    • Subversion变更单插件
  • Server

    • Django
  • 学习笔记

    • MySQL学习笔记
  • 运维

    • 服务器部署
    • Linux
  • 日常学习

    • 学习方法
关于
收藏
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Django

    • Django框架初体验(一)
    • Django框架初体验(二)
    • Django框架初体验(三)
    • Django框架初体验(四)
      • 编写一个简单的表单
      • 改良URLconf
      • 改良视图
    • 给django添加jwt授权
  • 学习笔记

  • 后端
  • Django
干巴爹兔
2020-07-04
目录

Django框架初体验(四)

# 编写一个简单的表单

让我们更新一下在上一个教程中编写的投票详细页面的模板 ("polls/detail.html") ,让它包含一个 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>
1
2
3
4
5
6
7
8
9
10
11
12

现在,让我们来创建一个 Django 视图来处理提交的数据。记住,在 教程第 3 部分 (opens new window) 中,我们为投票应用创建了一个 URLconf ,包含这一行:

path('<int:question_id>/vote/', views.vote, name='vote'),
1

我们还创建了一个 vote() 函数的虚拟实现。让我们来创建一个真实的版本。 将下面的代码添加到 polls/views.py :

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

from .models import Choice, Question
# ...
def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            '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=(question.id,)))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • request.POST (opens new window) 是一个类字典对象,让你可以通过关键字的名字获取提交的数据。 这个例子中, request.POST['choice'] 以字符串形式返回选择的 Choice 的 ID。 request.POST (opens new window) 的值永远是字符串。

    注意,Django 还以同样的方式提供 request.GET (opens new window) 用于访问 GET 数据 —— 但我们在代码中显式地使用 request.POST (opens new window) ,以保证数据只能通过 POST 调用改动。

  • 如果在 request.POST['choice'] 数据中没有提供 choice , POST 将引发一个 KeyError (opens new window) 。上面的代码检查 KeyError (opens new window) ,如果没有给出 choice 将重新显示 Question 表单和一个错误信息。

  • 在增加 Choice 的得票数之后,代码返回一个 HttpResponseRedirect (opens new window) 而不是常用的 HttpResponse (opens new window) 、 HttpResponseRedirect (opens new window) 只接收一个参数:用户将要被重定向的 URL(请继续看下去,我们将会解释如何构造这个例子中的 URL)。

    As the Python comment above points out, you should always return an HttpResponseRedirect (opens new window) after successfully dealing with POST data. This tip isn't specific to Django; it's good Web development practice in general.

  • 在这个例子中,我们在 HttpResponseRedirect (opens new window) 的构造函数中使用 reverse() 函数。这个函数避免了我们在视图函数中硬编码 URL。它需要我们给出我们想要跳转的视图的名字和该视图所对应的 URL 模式中需要给该视图提供的参数。 在本例中,使用在 教程第 3 部分 (opens new window) 中设定的 URLconf, reverse() 调用将返回一个这样的字符串:

'/polls/3/results/'
1

# 改良URLconf

首先,打开 polls/urls.py 这个 URLconf 并将它修改成:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]
1
2
3
4
5
6
7
8
9
10
11

# 改良视图

下一步,我们将删除旧的 index, detail, 和 results 视图,并用 Django 的通用视图代替。打开 polls/views.py 文件,并将它修改成:

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic

from .models import Choice, Question


class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]


class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'


def vote(request, question_id):
    ... # same as above, no changes needed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

我们在这里使用两个通用视图: ListView (opens new window) 和 DetailView (opens new window) 。这两个视图分别抽象“显示一个对象列表”和“显示一个特定类型对象的详细信息页面”这两种概念。

  • 每个通用视图需要知道它将作用于哪个模型。 这由 model 属性提供。
  • DetailView (opens new window) 期望从 URL 中捕获名为 "pk" 的主键值,所以我们为通用视图把 question_id 改成 pk 。

默认情况下,通用视图 DetailView (opens new window) 使用一个叫做 /_detail.html 的模板。在我们的例子中,它将使用 "polls/question_detail.html" 模板。template_name 属性是用来告诉 Django 使用一个指定的模板名字,而不是自动生成的默认名字。 我们也为 results 列表视图指定了 template_name —— 这确保 results 视图和 detail 视图在渲染时具有不同的外观,即使它们在后台都是同一个 DetailView (opens new window) 。

类似地,ListView (opens new window) 使用一个叫做 /_list.html 的默认模板;我们使用 template_name 来告诉 ListView (opens new window) 使用我们创建的已经存在的 "polls/index.html" 模板。

编辑 (opens new window)
#Django
上次更新: 2023/04/23, 17:02:50
Django框架初体验(三)
给django添加jwt授权

← Django框架初体验(三) 给django添加jwt授权→

最近更新
01
使用Vscode开发一个小插件
10-21
02
Vscode插件配置项监听
10-18
03
使用has属性构造必填效果
10-14
更多文章>
Theme by Vdoing | Copyright © 2020-2023 互联网ICP备案: 闽ICP备18027236号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式