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

如何在Django Admin中提交并存储两个关联模型表单的数据?

解决Django Admin嵌入关联模型表单提交问题

要让嵌入的RateCategoryGroup表单数据被提交并保存,需要修改FeeEarnerProfileAdmin的提交处理逻辑,同时调整模板确保表单能正常参与提交流程,具体步骤如下:

1. 修改Admin的change_view方法处理POST请求

在change_view中,优先处理POST请求里的RateCategoryGroupForm数据,验证通过后保存,再交由父类处理FeeEarnerProfile的保存逻辑:

class FeeEarnerProfileAdmin(VersionAdmin):
    change_form_template = "admin/organizations/fee_earner_profile/change_form.html"

    def change_view(self, request, object_id, form_url="", extra_context=None):
        # 获取关联的RateCategoryGroup实例
        rate_category_group_instance = RateCategoryGroup.objects.get(
            group_memberships__membership__fee_earner_profile__id=object_id
        )
        
        # 处理POST请求中的RateCategoryGroup表单数据
        if request.method == "POST":
            rate_category_group_form = RateCategoryGroupForm(
                request.POST, instance=rate_category_group_instance
            )
            if rate_category_group_form.is_valid():
                rate_category_group_form.save()
        else:
            # GET请求时正常初始化表单
            rate_category_group_form = RateCategoryGroupForm(instance=rate_category_group_instance)
        
        # 将表单传入上下文
        extra_context = extra_context or {}
        extra_context["rate_category_group_form"] = rate_category_group_form
        
        # 调用父类方法处理FeeEarnerProfile的保存
        return super().change_view(
            request, object_id, form_url, extra_context=extra_context
        )

2. 调整模板确保表单参与提交流程

直接渲染表单可能缺少CSRF令牌或无法和原Admin表单共用提交按钮,分两种场景处理:

场景1:单独提交关联表单

给嵌入的表单添加独立提交按钮,需要手动加入CSRF令牌:

{% extends "admin/change_form.html" %}
{% load i18n admin_urls static admin_modify %}

{% block content %}
    {{ block.super }}
    <hr>
    <h2>Rate Category Group</h2>
    <form method="post">
        {% csrf_token %}
        {{ rate_category_group_form.as_p }}
        <input type="submit" value="保存分组修改" class="default">
    </form>
{% endblock %}

场景2:和原表单共用提交按钮

将关联表单的字段嵌入原Admin的<form>标签内,点击原"保存"按钮即可同时提交两个模型的数据:

{% extends "admin/change_form.html" %}
{% load i18n admin_urls static admin_modify %}

{% block content %}
    {% block form_top %}{% endblock %}
    <div class="module aligned">
        {% block field_sets %}
            {{ block.super }}
        {% endblock %}
        
        <!-- 嵌入RateCategoryGroup表单字段到原表单中 -->
        <h2>Rate Category Group</h2>
        {% for field in rate_category_group_form %}
            <div class="form-row">
                {{ field.label_tag }} {{ field }}
                {% if field.help_text %}
                    <p class="help">{{ field.help_text|safe }}</p>
                {% endif %}
                {% for error in field.errors %}
                    <p class="error">{{ error }}</p>
                {% endfor %}
            </div>
        {% endfor %}
    </div>
    
    {% block submit_buttons_bottom %}{{ block.super }}{% endblock %}
{% endblock %}

3. 可选:添加表单前缀避免字段冲突

如果两个模型存在同名字段,初始化表单时添加prefix参数区分:

# 在change_view中初始化表单时
rate_category_group_form = RateCategoryGroupForm(
    request.POST if request.method == "POST" else None,
    instance=rate_category_group_instance,
    prefix="rate_group"
)

注意事项

  • 确保RateCategoryGroupForm包含所有需要编辑的字段,且当前用户有修改RateCategoryGroup的权限。
  • 如果关联的RateCategoryGroup实例可能不存在,需要捕获DoesNotExist异常,补充创建实例的逻辑。
  • 此方法确实不属于Django Admin的最佳实践,更推荐使用InlineModelAdmin,但针对需求可实现功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 04:50:27