Django更新模型字段时如何向指定列追加数据而非覆盖原有内容
Django 表单更新时追加字段数据实现方案
先修复现有代码的显性问题
你现有代码存在几处书写错误,会导致逻辑无法正常运行,先做修正:
models.py 修正
- 移除
current_commands字段定义末尾多余的逗号,该逗号会导致字段被识别为元组而非模型字段 - 给
Executed_Commands设置默认空字符串,避免首次操作时取到None触发拼接错误
CHOICES = [ ('Sleep', "Sleep"), ('Open SSH_Tunnel', 'Open SSH_Tunnel'), ('Close SSH_Tunnel', 'Close SSH_Tunnel'), ('Open TCP_Tunnel', 'Open TCP_Tunnel'), ('Close TCP_Tunnel', 'Close TCP_Tunnel'), ('Open Dynamic', 'Open Dynamic'), ('Close Dynamic', 'Close Dynamic'), ('Task', 'Task'), ] class Command_Node(models.Model): host_id = models.ForeignKey(Beacon, on_delete=models.CASCADE) current_commands = models.CharField(choices=CHOICES, max_length=50, null=True) Executed_Commands = models.CharField('Executed_Commands', max_length=2000, null=True, default="") def __str__(self): return str(self.host_id)
forms.py 修正
- 自定义字段必须写在
Meta类外部,写在内部不会生效 - 修正
current_comamnds的拼写错误为current_commands
class Command_Form(ModelForm): host_id = forms.ModelChoiceField( required=True, queryset=Beacon.objects.all(), widget=forms.SelectMultiple( attrs={ 'class': 'form-control' }, ) ) current_commands = forms.ChoiceField( required=True, choices=CHOICES ) class Meta: model = Command_Node fields = ( 'host_id', 'current_commands' )
修改视图实现历史命令追加逻辑
核心思路是表单校验通过后,不直接执行form.save()写入数据库,而是先通过commit=False拿到暂存的模型实例,将本次提交的新命令追加到Executed_Commands字段后再执行保存,不会覆盖原有历史数据。
这里用换行符\n分隔不同历史命令,方便后续读取时拆分展示。
def update(request, host_id): host_obj = Command_Node.objects.get(pk=host_id) form = Command_Form(request.POST or None, instance=host_obj) if form.is_valid(): # 暂存实例,不立即写入数据库 instance = form.save(commit=False) new_command = instance.current_commands # 追加历史命令,空值时不加分隔符避免开头空行 if instance.Executed_Commands: instance.Executed_Commands = f"{instance.Executed_Commands}\n{new_command}" else: instance.Executed_Commands = new_command # 最终写入数据库 instance.save() return redirect('home') return render (request, 'update.html', {'host_id':host_obj,'form':form})
可选优化方案
如果你的Django版本 >= 3.1,建议将Executed_Commands替换为内置的JSONField,直接存储命令列表,不需要手动处理字符串分隔,也不会出现CharField长度溢出的问题,后续查询、统计历史命令更方便:
- 模型修改:
from django.db import models # 其他代码不变 class Command_Node(models.Model): host_id = models.ForeignKey(Beacon, on_delete=models.CASCADE) current_commands = models.CharField(choices=CHOICES, max_length=50, null=True) # 用JSONField存列表,默认空列表 Executed_Commands = models.JSONField(default=list) def __str__(self): return str(self.host_id)
- 视图追加逻辑修改:
if form.is_valid(): instance = form.save(commit=False) new_command = instance.current_commands # 直接向列表追加元素即可 instance.Executed_Commands.append(new_command) instance.save() return redirect('home')
内容的提问来源于stack exchange,提问作者Steven Pinkerton
相关产品推荐
相关产品推荐

