【实战案例】Django框架表单处理及数据库交互

embedded/2024/10/25 10:34:05/

本文基于之前内容列表如下:
【图文指引】5分钟搭建Django轻量级框架服务
【实战案例】Django框架基础之上编写第一个Django应用之基本请求和响应
【实战案例】Django框架连接并操作数据库MySQL相关API
【实战案例】Django框架使用模板渲染视图页面及异常处理

更新编写的投票详细页面的模板"polls/detail.html"让它包含一个 form表单元素:
(超详细注释版)

<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>这是detail的模板渲染</title>
</head>
<body>
<!--action属性使用{\% url %}模板标签动态生成投票处理的URL。'polls:vote'是命名的URL模式,question.id是传递给该URL的参数(问题的ID)。-->
<!--method="post"指明表单数据通过POST请求提交,适合用于修改服务器端数据(这里是投票)-->
<form action="{% url 'polls:vote' question.id %}" method="post"><!--Django的跨站请求伪造(CSRF)保护机制。它在表单中插入一个隐藏字段,确保请求来自同一个站点,以防止恶意攻击。-->{% csrf_token %}<!--<fieldset>用于分组相关元素,通常与<legend>结合使用,提升可读性和可访问性。--><fieldset><legend><h1>{{ question.question_text }}</h1></legend><!--如果存在错误消息(如用户未选择选项),会显示在表单中。error_message是从视图传递到模板的上下文变量。-->{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}<!--这个循环遍历当前问题的所有选择项(choice_set是Django为一对多关系生成的反向关系管理器)。--><!--对于每个选择项,生成一个单选框(<input type="radio">)和对应的标签(<label>)。--><!--id="choice{\{ forloop.counter }}"为每个单选框生成唯一的ID,forloop.counter是Django模板中的内置变量,从1开始计数。--><!--value="{\{ choice.id }}"将每个单选框的值设置为选择项的ID,以便在提交表单时识别所选的选择项。-->{% 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>
</body>
</html>

之前创建的URLconf位于polls/urls.py中

python">path("<int:question_id>/vote/", views.vote, name="vote"),

在polls/views.py中更新如下代码:

python">from django.db.models import F
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reversefrom .models import Choice, Question# ...
def vote(request, question_id):# 使用 get_object_or_404 函数获取指定问题对象。如果未找到,则返回404错误页面。question = get_object_or_404(Question, pk=question_id)try:# 从POST请求中获取选中的选择项ID,并在该问题的选择集中查找对应的选择项。selected_choice = question.choice_set.get(pk=request.POST["choice"])except (KeyError, Choice.DoesNotExist):# 如果在POST请求中没有找到选择项,或选择项不存在,执行以下操作:# Redisplay the question voting form with an error message.return render(request,  # 当前请求对象"polls/detail.html",  # 渲染的模板{"question": question,  # 重新传递问题对象,以便在模板中显示"error_message": "You didn't select a choice.",  # 错误消息,提示用户未选择任何选项},)else:# 如果成功找到选中的选择项,则增加其票数selected_choice.votes = F("votes") + 1  # 使用 F 表达式进行原子操作,避免竞争条件selected_choice.save()  # 保存更新后的选择项# 返回一个 HttpResponseRedirect,以防止用户在提交后刷新页面导致重复提交return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))# 当有人对 Question 进行投票后, vote() 视图将请求重定向到 Question 的结果界面
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模板:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>这是results的模板渲染</title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
<!--<ul>标签用于创建一个无序列表-->
<!--{\% for choice in question.choice_set.all %}:这是一个循环,遍历当前问题的所有选择项。question.choice_set.all是Django的反向关系管理器,用于获取与该问题相关的所有选择项。-->
<!--vote{\{ choice.votes|pluralize }}:使用pluralize过滤器来处理单复数形式。如果得票数为1,显示“vote”,否则显示“votes”。这使得文本更自然,适应不同的得票数。-->
<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>
</body>
</html>

通过上述更新,访问http://localhost:8000/polls/可见如下页面:
在这里插入图片描述
投票页面如下所示:
在这里插入图片描述
在这里插入图片描述
选择选项并点击vote按钮可进行投票,投票后显示票数页面且可再次投票
在这里插入图片描述
对应数据库的数据也会更新
在这里插入图片描述


http://www.ppmy.cn/embedded/132305.html

相关文章

electron展示下载进度条

我们使用electron下载文件时&#xff0c;会发现不像浏览器一样会有地方展示下载进度&#xff0c;这导致下载一些大文件时不知道下载进度到哪里了 下面我们通过electron提供的will-download监听和element-plus中的ElNotification和ElProgress组件实现这一功能 实现逻辑 触发…

jmeter基础00_课程内容概述

课程目标 基础组件、函数、beanshell脚本的使用/编写 界面编写接口测试case&#xff0c;执行脚本&#xff0c;查看请求结果。 接口自动化测试执行&#xff0c;生成html报告(jmeter自带模板)&#xff0c;发送邮件通知。 课程大纲 1、环境准备-安装jdk&#xff08;windows、m…

华纳云:如何通过CDN降低服务器网络延迟?

CDN是由分布在不同地理位置的服务器群组组成的网络&#xff0c;其核心功能是将内容缓存到靠近用户的位置&#xff0c;从而加速内容的交付。当用户访问某个网站或应用时&#xff0c;CDN会根据用户的IP地址将请求转发到离用户最近的服务器节点。该节点会将内容从源服务器中读取出…

深度探索强化学习及其在智能决策中的应用

&#x1f680; 深度探索强化学习及其在智能决策中的应用 目录 &#x1f31f; 强化学习的基本概念&#x1f4a1; Q-learning算法解析&#x1f9e0; 深度Q网络&#xff08;DQN&#xff09;与深度强化学习&#x1f3ae; 强化学习的应用场景 1. &#x1f31f; 强化学习的基本概念…

前端方案:播放的视频加水印或者文字最佳实践

前言&#xff1a; 很多时候&#xff0c;视频的转码工作在后端&#xff0c;我们前端是拿到可以播放的链接进行播放即可。但是总是会出现一些定制化的需求&#xff0c;比如在视频的某个区域贴上水印、标识或者文字。这个时候大部分是由前端来操作的。 直接去修改播放器里的东西…

k8s知识点总结

docker 名称空间 分类 Docker中的名称空间用于提供进程隔离&#xff0c;确保容器之间的资源相互独立。主要分类包括&#xff1a; PID Namespace&#xff1a;进程ID隔离&#xff0c;使每个容器有自己的进程树&#xff0c;容器内的进程不会干扰其他容器或主机上的进程。 NET Nam…

MongoDB-Plus

MongoDB-Plus是一款功能强大的数据库工具&#xff0c;它基于MongoDB&#xff0c;提供了更丰富的功能和更便捷的操作方式。以下是一篇关于MongoDB-Plus轻松上手的详细指南&#xff0c;旨在帮助初学者快速掌握其安装、配置和基础操作。 一、MongoDB-Plus概述 MongoDB是一款由C编…

数据结构——队列和栈

目录 一、栈 1、概念与结构 2、栈的结构与初始化 3、入栈 4、出栈 5、取栈顶元素 6、取栈中有效元素个数 7、栈是否为空 二、队列 1、概念与结构 2、队列的结构与初始化 3、入队列 4、出队列 5、取队头数据 6、取队尾数据 7、队列判空 8、队列中有效元素个数 练习题目链 一…