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

Django模态框多表单编辑:如何传入Instance加载已有数据

Django同一页面多模态表单编辑:传入instance显示已有数据

我在Django应用的同一页面使用多个模态框打开的表单,已通过自定义函数实现基础功能,但作为新手,添加编辑功能时遇到困难——不清楚应在何处传入instance,使表单能够显示该实例的已有数据。

现有代码片段

视图中的表单变量:

edit_employment_form = _get_form(request, EditEmploymentForm, "edit_employment_form_pre")

区分表单的自定义函数:

def _get_form(request, formcls, prefix):
        data = request.POST if prefix in request.POST else None
        return formcls(data, prefix=prefix)

完整视图代码(已获取用于筛选实例的employment_id):

@login_required
def person_profile(request, person_id):
    current_user = request.user
    user = Person.objects.get(user=current_user)
    people = Person.objects.all()
    jobs = Job.objects.all()
    person = Person.objects.get(pk=person_id)
    employments = Employments.objects.filter(person_id=person_id).order_by("-start_date")
    workflows = Workflows.objects.filter(person_id=person_id).order_by("-workflow_date")
    sources = Sources.objects.filter(person_id=person_id).order_by("-source_date")
    tags = Tags.objects.filter(person_id=person_id)
    comments = Comments.objects.filter(person_id=person_id)
    person_calls = ScheduledCalls.objects.filter(person_id=person_id).order_by("-date")
    scheduled_calls = ScheduledCalls.objects.filter(user_id=user.id).order_by("-date")
    reminders = Reminders.objects.filter(person_id=person_id)
    notes = Notes.objects.filter(user_id=person_id)
    gdpr = GDPR.objects.filter(person_id=person_id).order_by("-is_valid")
    valid_gdpr_filter = GDPR.objects.filter(person_id=person_id, is_valid="Valid")
    license_b_filter = Licenses.objects.filter(person_id=person_id, license="B")
    license_c_filter = Licenses.objects.filter(person_id=person_id, license="C")
    license_ce_filter = Licenses.objects.filter(person_id=person_id, license="CE")
    license_95_filter = Licenses.objects.filter(person_id=person_id, license="95")
    skill_fd_filter = Skills.objects.filter(person_id=person_id, skill="FD experience")
    skill_op_filter = Skills.objects.filter(person_id=person_id, skill="OP experience")
    skill_ce_filter = Skills.objects.filter(person_id=person_id, skill="CE driver experience")
    skill_tl_filter = Skills.objects.filter(person_id=person_id, skill="Team Leading experience")


    if valid_gdpr_filter:
        valid_gdpr = GDPR.objects.get(person_id=person_id, is_valid="Valid")
        end_date_calc = ((valid_gdpr.consent_date + timedelta(days=1095)) - date.today())
        days = int(str(end_date_calc).split(" ", 1)[0])

        if days > 30:
            consent_ends_in = "more than a month"
        elif days > 14:
            consent_ends_in = "around 2 weeks"
        elif days < 14:
            consent_ends_in = "less than 2 weeks!"        
    else:
        valid_gdpr = None
        consent_ends_in = None

    if license_b_filter: 
        license_b = Licenses.objects.get(person_id=person_id, license="B")
    else:
        license_b = None

    if license_c_filter: 
        license_c = Licenses.objects.get(person_id=person_id, license="C")
    else:
        license_c = None  

    if license_ce_filter: 
        license_ce = Licenses.objects.get(person_id=person_id, license="CE")
    else:
        license_ce = None  

    if license_95_filter: 
        license_95 = Licenses.objects.get(person_id=person_id, license="95")
    else:
        license_95 = None                  

    if skill_fd_filter: 
        skill_fd = Skills.objects.get(person_id=person_id, skill="FD experience")
    else:
        skill_fd = None

    if skill_op_filter: 
        skill_op = Skills.objects.get(person_id=person_id, skill="OP experience")
    else:
        skill_op = None

    if skill_ce_filter: 
        skill_ce = Skills.objects.get(person_id=person_id, skill="CE driver experience")
    else:
        skill_ce = None

    if skill_tl_filter: 
        skill_tl = Skills.objects.get(person_id=person_id, skill="Team Leading experience")
    else:
        skill_tl = None            


    if request.method == "POST":
        new_employment_form = _get_form(request, EmploymentForm, "new_employment_form_pre")
        new_application_form = _get_form(request, ApplicationForm, "new_application_form_pre")
        new_consent_form = _get_form(request, GDPRForm, "new_consent_form_pre")
        edit_employment_form = _get_form(request, EditEmploymentForm, "edit_employment_form_pre")
        employment_id = request.POST.get("employment_id")
        print(employment_id)    

        if new_employment_form.is_bound and new_employment_form.is_valid():
            new_employment_form.instance.person_id = person
            new_employment_form.instance.hired_by = user
            new_employment_form.save(commit=False)
            new_employment_form.save()
            person.person_type = "Current Employee"
            person.save()
            candidate_gdpr = GDPR.objects.get(person_id=person_id, is_valid="Valid")
            candidate_gdpr.is_valid = "Invalid"
            candidate_gdpr.save()
            return redirect("person_profile", person_id)
        
        if new_application_form.is_bound and new_application_form.is_valid():
            new_application_form.instance.person_id = person
            new_application_form.save(commit=False)
            new_application_form.save()
            workflow = Workflows()
            workflow.workflow_date = date.today()
            workflow.stage = "New Applicant"
            workflow.person_id = Person.objects.get(id=person_id)
            workflow.save()
            return redirect("person_profile", person_id)
        
        if new_consent_form.is_bound and new_consent_form.is_valid():
            file = request.POST.get("consent_file")
            input_date = request.POST.get("consent_date")
            consent_date = datetime.strptime(input_date, "%Y-%m-%d").date()
            new_consent_form.instance.consent_file = file
            new_consent_form.instance.person_id = person
            new_consent_form.instance.consent_date = consent_date
            new_consent_form.instance.consent_end_date = consent_date + timedelta(days=1095)
            new_consent_form.save(commit=False)
            new_consent_form.save()
            return redirect("person_profile", person_id)
        
        if edit_employment_form.is_bound and edit_employment_form.is_valid():
            return redirect("person_profile", person_id)

        
        
    return render(request, "person/person_profile.html", {"person" : person,
                                                          "people" : people,
                                                          "jobs" : jobs, 
                                                          "employments" : employments,
                                                          "workflows" : workflows,
                                                          "sources" : sources,
                                                          "tags" : tags,
                                                          "comments" : comments,
                                                          "scheduled_calls" : scheduled_calls,
                                                          "reminders" : reminders,
                                                          "notes" : notes,
                                                          "gdpr" : gdpr,
                                                          "valid_gdpr" : valid_gdpr,
                                                          "consent_ends_in": consent_ends_in,
                                                          "license_b" : license_b,
                                                          "license_c" : license_c,
                                                          "license_ce" : license_ce,
                                                          "license_95" : license_95,
                                                          "skill_fd" : skill_fd,
                                                          "skill_op" : skill_op,
                                                          "skill_ce" : skill_ce,
                                                          "skill_tl" : skill_tl,
                                                          "person_calls" : person_calls,
                                                          "scheduled_calls" : scheduled_calls,
                                                          "new_employment_form" : EmploymentForm(prefix = "new_employment_form_pre"),
                                                          "new_application_form" : ApplicationForm(prefix = "new_application_form_pre"),
                                                          "new_consent_form" : GDPRForm(prefix="new_consent_form_pre"),
                                                          "edit_employment_form" : EditEmploymentForm(prefix="edit_employment_form_pre"),
                                                          })

解决方案

1. 修改自定义函数支持instance参数

让_get_form能接收并传递instance给表单,这样编辑时就能传入要修改的实例:

def _get_form(request, formcls, prefix, instance=None):
    data = request.POST if prefix in request.POST else None
    # 把instance传入表单构造器
    return formcls(data, prefix=prefix, instance=instance)

2. 在视图中获取要编辑的Employment实例

不管是GET请求(打开模态框)还是POST请求(提交编辑),都需要先拿到对应的employment_id,再查询出实例:
在视图顶部、if request.method == "POST"之前添加:

# 从POST或GET参数中获取employment_id
employment_id = request.POST.get("employment_id") or request.GET.get("employment_id")
employment_instance = None
if employment_id:
    try:
        # 确保是当前person的employment,避免越权
        employment_instance = Employments.objects.get(pk=employment_id, person_id=person_id)
    except Employments.DoesNotExist:
        employment_instance = None

3. 初始化编辑表单时传入instance

  • POST请求中:修改初始化edit_employment_form的代码,传入employment_instance:
edit_employment_form = _get_form(request, EditEmploymentForm, "edit_employment_form_pre", instance=employment_instance)
  • GET请求返回时:替换原来直接实例化表单的代码,改用_get_form并传入实例:
"edit_employment_form" : _get_form(request, EditEmploymentForm, "edit_employment_form_pre", instance=employment_instance),

4. 完善编辑表单的保存逻辑

现在表单已经绑定了实例,直接调用save()就能更新数据:

if edit_employment_form.is_bound and edit_employment_form.is_valid():
    edit_employment_form.save()
    return redirect("person_profile", person_id)

5. 前端传递employment_id

点击编辑按钮时,要把对应employment的ID传递给模态框里的表单,比如用Bootstrap模态框的事件:

  • 编辑按钮添加data-employment-id属性:
<button type="button" data-bs-toggle="modal" data-bs-target="#editEmploymentModal" data-employment-id="{{ emp.id }}">
  编辑工作经历
</button>
  • 模态框表单里加一个隐藏字段:
<form method="post" id="editEmploymentForm" prefix="edit_employment_form_pre">
  {% csrf_token %}
  <input type="hidden" name="employment_id" id="employment_id">
  <!-- 其他表单字段 -->
</form>
  • 用JavaScript在模态框显示时赋值:
const editModal = document.getElementById('editEmploymentModal');
editModal.addEventListener('show.bs.modal', function (event) {
  const button = event.relatedTarget;
  const empId = button.getAttribute('data-employment-id');
  document.getElementById('employment_id').value = empId;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 04:26:59