如何在Django表单中展示SQL查询结果并实现图书复选框多选提交
Django书店图书选购表单实现方案
需求说明
- 从MSSQL数据库读取Books表所有图书数据渲染到表单
- 每条图书记录前增加复选框供用户勾选选购
- 图书信息字段使用
CharField,设置disabled=True禁止编辑,采用Textarea作为输入小部件 - 表单提交后提取所有选中图书的UID列表,用于后续订单入库等业务逻辑
- 现有环境:Django对接SQL Server 2019正常,数据库连接配置无误
代码修改步骤
1. 重写forms.py
原有单ModelForm仅支持单条图书数据,需要调整为支持多条数据的表单集,同时新增复选框字段,配置只读规则:
from django.forms import ModelForm, modelformset_factory from django import forms from .models import Books class BookRowForm(forms.ModelForm): # 新增选购复选框,非必填 selected = forms.BooleanField(required=False, label="选购") class Meta: model = Books fields = ['selected', 'uid', 'bookname', 'author', 'category', 'qty', 'price'] # 统一给所有图书信息字段设置Textarea小部件、禁用编辑、非必填 widgets = { 'uid': forms.Textarea(attrs={'disabled': True, 'rows':1}), 'bookname': forms.Textarea(attrs={'disabled': True, 'rows':1}), 'author': forms.Textarea(attrs={'disabled': True, 'rows':1}), 'category': forms.Textarea(attrs={'disabled': True, 'rows':1}), 'qty': forms.Textarea(attrs={'disabled': True, 'rows':1}), 'price': forms.Textarea(attrs={'disabled': True, 'rows':1}), } # 生成图书表单集,不额外生成空行,默认拉取所有图书数据 BookFormSet = modelformset_factory(Books, form=BookRowForm, extra=0)
2. 修正views.py业务逻辑
原有视图未处理GET请求初始化、表单集绑定、选中UID提取逻辑,调整后代码如下:
from django.shortcuts import render from .models import Books from .forms import BookFormSet def Homepage(request): selected_uids = [] if request.method == 'POST': # 绑定提交的POST数据到表单集 formset = BookFormSet(request.POST, queryset=Books.objects.all()) if formset.is_valid(): # 遍历表单提取选中的图书UID for book_form in formset: if book_form.cleaned_data.get('selected'): selected_uids.append(book_form.cleaned_data.get('uid')) # 此处可直接使用selected_uids写入orders订单表 # 例:Order.objects.bulk_create([Order(book_id=uid) for uid in selected_uids]) else: # GET请求初始化空表单集,绑定所有图书数据 formset = BookFormSet(queryset=Books.objects.all()) return render(request, 'Homepage.html', { 'formset': formset, 'selected_uids': selected_uids # 可选:传选中结果到模板做提示 })
3. 调整Homepage.html模板
原有模板未适配表单集渲染规则,需要补充表单集必须的管理字段,调整渲染顺序把复选框放在每条图书最前面:
<html> <head> <title>HomePage</title> <link rel="icon" type="image/x-icon" href="/MainWinIcon.ico"> </head> <body style="text-align:center;vertical-align:middle;background-color:rgb(62,245,226);"> <h1>Welcome to HomePage Select the Books you want and Press Submit</h1> <form method="post"> {% csrf_token %} <!-- 表单集必须渲染管理字段,否则会触发校验错误 --> {{ formset.management_form }} <fieldset style="max-width: 800px; margin: 0 auto;"> {% for book_form in formset %} <div style="background: #fff; border: 1px solid #333; margin: 10px 0; padding: 15px; text-align: left;"> <!-- 最前面渲染选购复选框 --> <div style="padding-bottom: 10px; border-bottom: 1px solid #eee;"> {{ book_form.selected }} <label>选购此书</label> </div> <!-- 渲染隐藏字段 --> {% for hidden in book_form.hidden_fields %} {{ hidden }} {% endfor %} <!-- 渲染只读图书信息字段 --> {% for field in book_form.visible_fields %} {% if field.name != 'selected' %} <div style="margin: 8px 0;"> <label style="display: inline-block; width: 80px;">{{ field.label }}:</label> {{ field }} </div> {% endif %} {% endfor %} </div> {% endfor %} <input type="submit" value="Submit" style="padding: 8px 20px; margin: 20px 0;"> </fieldset> </form> <h2 style="text-align:center;vertical-align:middle;background-color:grey">Books List</h2> </body> </html>
注意事项
- 表单集必须渲染
{{ formset.management_form }},否则Django会抛出校验异常 - 字段设置
disabled=True后,前端无法修改内容,Django会自动用绑定的模型实例值填充清洗后的数据,无需额外添加隐藏传值字段 - 提取到的
selected_uids是纯UID列表,可以直接对接后续订单创建、库存扣减等业务逻辑 - 现有SQL Server 2019连接配置可直接复用,Django ORM会自动完成数据查询,不需要手写原生SQL
内容的提问来源于stack exchange,提问作者Pooria
相关产品推荐
相关产品推荐

