Django教程:编写投票应用第四部分 - 表单处理与通用视图

Django教程:编写投票应用第四部分 - 表单处理与通用视图

django django/django: 是一个用于 Python 的高级 Web 框架,可以用于快速开发安全和可维护的 Web 应用程序,提供了多种内置功能和扩展库,支持多种数据库和模板引擎。 django 项目地址: https://gitcode.com/gh_mirrors/dj/django

表单处理基础

在Django投票应用的这一部分,我们将重点学习如何处理表单数据并简化视图代码。表单是Web开发中用户交互的核心组件,Django提供了强大的工具来处理表单数据。

创建投票表单

首先,我们需要更新投票详情页面的模板,添加一个表单让用户进行投票:

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% 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 %}
</fieldset>
<input type="submit" value="Vote">
</form>

这个表单有几个关键点需要注意:

  1. 使用POST方法提交数据,因为这会修改服务器端数据
  2. 包含CSRF令牌以防止跨站请求伪造攻击
  3. 每个选项的值设置为对应选项的ID
  4. 使用forloop.counter生成唯一的ID属性

处理表单提交

接下来,我们需要实现处理投票的视图函数:

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):
        return render(request, "polls/detail.html", {
            "question": question,
            "error_message": "You didn't select a choice.",
        })
    else:
        selected_choice.votes = F("votes") + 1
        selected_choice.save()
        return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))

这个视图函数做了以下几件事:

  1. 获取问题对象或返回404错误
  2. 尝试从POST数据中获取用户选择的选项
  3. 如果用户没有选择选项,重新显示表单并提示错误
  4. 使用F()表达式避免竞态条件更新票数
  5. 重定向到结果页面防止重复提交

结果页面实现

投票完成后,我们需要显示结果页面:

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

对应的模板显示每个选项及其得票数:

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

使用通用视图简化代码

Django提供了通用视图来简化常见模式。我们的index、detail和results视图都可以用通用视图重写。

修改URL配置

首先更新URL配置:

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"),
]

注意URL参数名从question_id改为pk,这是通用视图的约定。

实现通用视图

然后重写视图为基于类的通用视图:

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

    def get_queryset(self):
        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"

这些通用视图自动处理了许多常见任务:

  1. ListView自动获取模型列表并传递给模板
  2. DetailView自动根据pk获取单个对象
  3. 我们可以通过template_name指定自定义模板路径
  4. 通过context_object_name自定义上下文变量名

总结

本部分教程我们学习了:

  1. 如何在Django中处理表单提交
  2. 使用POST方法修改服务器数据的最佳实践
  3. 实现投票功能并显示结果
  4. 使用Django通用视图简化代码

通用视图是Django强大的功能之一,可以显著减少重复代码。它们抽象了常见的Web开发模式,让我们可以专注于应用特有的逻辑。

在下一部分中,我们将学习如何测试这个投票应用,确保它的稳定性和可靠性。

django django/django: 是一个用于 Python 的高级 Web 框架,可以用于快速开发安全和可维护的 Web 应用程序,提供了多种内置功能和扩展库,支持多种数据库和模板引擎。 django 项目地址: https://gitcode.com/gh_mirrors/dj/django

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钱恺才Grace

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值