You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Forms提交时新建记录而非更新已有command_node条目问题

问题原因

无参数调用ModelForm的save()方法时,Django默认执行新建模型实例的逻辑,不会自动关联查询选中主机已存在的command_node记录做更新,因此每次提交都会生成全新的关联记录。

修复步骤

1. 修正models.py的错误导入与字段隐患

当前代码中从tkinter、turtle导入的内容属于无效错误导入,直接删除即可;另外外键字段命名为host_id会和Django外键自动生成的_id后缀属性冲突,建议加db_column参数指定数据库列名,避免字段映射混乱。修正后代码:

from django.db import models

class beacon(models.Model):
    host_id = models.BigAutoField('Id', primary_key=True)
    hostname = models.CharField('Hostname', max_length=200)
    internalIp = models.CharField('Internal-IP', max_length=200)
    externalIp = models.CharField('External-IP', max_length=200)
    current_user = models.CharField('Current_User', max_length=200)
    os = models.CharField('OS', max_length=200)
    admin = models.CharField('Admin', max_length=200)
    
    def __str__(self):
        return self.hostname

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 = models.ForeignKey(beacon, on_delete=models.CASCADE, db_column='host_id')
    current_commands = models.CharField(choices=CHOICES, max_length=50, null=True)
    previous_commands = models.CharField('previous_commands', max_length=2000, null=True)
    
    def __str__(self):
        return str(self.host)

如果不想修改原有外键字段名host_id,可以保留原命名,只需把后续视图代码中查询用到的host=参数替换为host_id=即可。

2. 重写视图提交逻辑

不要直接调用form.save(),表单校验通过后,取出选中的目标主机和命令,用Django ORM的update_or_create方法实现「存在即更新、不存在才新建」的逻辑,修正后代码:

from django.shortcuts import render
from .models import beacon, command_node
from .forms import Command_Form


def home(request):
    form = Command_Form()
    if request.method == "POST":
        form = Command_Form(request.POST)
        if form.is_valid():
            # 从清洗后的表单数据取选中的目标主机、待下发命令
            target_host = form.cleaned_data['host']
            target_command = form.cleaned_data['current_commands']
            # 按主机匹配已有command_node记录,更新current_commands字段
            command_node.objects.update_or_create(
                host=target_host,
                defaults={'current_commands': target_command}
            )
            # 返回空白表单避免重复提交
            return render(request, 'home.html', {"form": Command_Form()})

    return render(request, 'home.html', {"form": form})

补充说明
  • 如果你的Command_Form中主机选择字段的命名不是host,将上述代码中对应取值、查询的字段名替换为表单实际字段名即可。
  • 后续实现「命令执行完成后迁移到历史记录」逻辑时,只需在客户端回调接口中查询对应主机的command_node记录,将current_commands的值追加到previous_commands后清空current_commands字段即可。
  • 修改模型字段后需要重新执行python manage.py makemigrations和python manage.py migrate同步数据库结构。

内容的提问来源于stack exchange,提问作者Steven Pinkerton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:42:25