如何在Django中创建同时更新多用户多字段的表单?
Django批量更新Cash记录的表格表单解决方案
问题背景
现有两个Django模型Members和Cash,每个Member对应一条Cash记录,用于记录每月缴费状态(布尔字段)。需要创建一个表格形式的表单,一次性批量更新所有成员的缴费状态,避免为每个成员单独创建表单。
模型代码
class Members(models.Model): nim = models.IntegerField(default=0) name = models.CharField(max_length=40) position = models.CharField( max_length=30, choices=POSITION_OPTION, ) year = models.IntegerField() program = models.CharField(max_length=30) potrait = models.CharField(max_length=100, default='NO PHOTO') class Cash(models.Model): name = models.ForeignKey(Members, on_delete=models.CASCADE) jan = models.BooleanField(default=False) feb = models.BooleanField(default=False) mar = models.BooleanField(default=False) apr = models.BooleanField(default=False) may = models.BooleanField(default=False) jun = models.BooleanField(default=False) jul = models.BooleanField(default=False) aug = models.BooleanField(default=False) sep = models.BooleanField(default=False)
解决方案
1. 视图函数实现
在views.py中编写视图,负责渲染表单和处理批量更新请求:
from django.shortcuts import render, redirect from .models import Members, Cash def bulk_update_cash(request): # 获取所有成员及其对应的Cash记录,用prefetch_related优化查询性能 members = Members.objects.prefetch_related('cash_set').all() # 确保每个成员都有对应Cash记录,避免新成员无缴费记录的问题 for member in members: Cash.objects.get_or_create(name=member) if request.method == 'POST': # 遍历每个成员,处理提交的表单数据 for member in members: cash = member.cash_set.first() # 逐个处理每个月份的复选框状态 for month in ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep']: field_name = f'cash_{member.id}_{month}' # 复选框被勾选则设为True,否则为False setattr(cash, month, request.POST.get(field_name) == 'on') cash.save() return redirect('bulk_update_cash') # 更新完成后重定向回原页面 context = {'members': members} return render(request, 'bulk_update_cash.html', context)
2. 模板文件实现
创建templates/bulk_update_cash.html,渲染表格形式的批量更新表单:
<form method="POST"> {% csrf_token %} <div class="s-table-container"> <table class="s-table"> <thead> <tr> <th>NIM</th> <th>Name</th> <th>January</th> <th>February</th> <th>March</th> <th>April</th> <th>May</th> <th>June</th> <th>July</th> <th>August</th> <th>September</th> </tr> </thead> <tbody> {% for member in members %} {% with cash=member.cash_set.first %} <tr> <td>{{ member.nim }}</td> <td>{{ member.name }}</td> <td><input type="checkbox" name="cash_{{ member.id }}_jan" {% if cash.jan %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_feb" {% if cash.feb %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_mar" {% if cash.mar %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_apr" {% if cash.apr %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_may" {% if cash.may %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_jun" {% if cash.jun %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_jul" {% if cash.jul %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_aug" {% if cash.aug %}checked{% endif %}></td> <td><input type="checkbox" name="cash_{{ member.id }}_sep" {% if cash.sep %}checked{% endif %}></td> </tr> {% endwith %} {% endfor %} </tbody> </table> </div> <button type="submit">UPDATE RECORD</button> </form>
3. URL配置
在urls.py中添加对应的URL路由:
from django.urls import path from .views import bulk_update_cash urlpatterns = [ # 其他路由... path('bulk-update-cash/', bulk_update_cash, name='bulk_update_cash'), ]
核心逻辑说明
- 表单字段命名规则:采用
cash_{member_id}_{month}格式,确保视图能通过成员ID和月份字段名,精准定位到对应的Cash记录和字段。 - 视图中用
get_or_create自动为新成员创建Cash记录,避免数据缺失。 - 批量更新时通过
setattr动态设置Cash对象的字段值,简化重复代码。
内容的提问来源于stack exchange,提问作者isca_
相关产品推荐
相关产品推荐

