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

Django:如何从URL参数设置ModelForm外键字段默认值并只读提交?

解决外键字段通过URL参数设置默认值并只读提交的问题

我来帮你搞定这个问题,核心是要让表单正确识别外键字段的参数,同时保证字段只读且能被正常提交。下面分步骤修改你的代码:

1. 修改视图(views.py):初始化表单时设置外键初始值

首先在视图里,我们要把URL传递的reference_id作为表单reference字段的初始值,同时要确保这个ID对应的Orders实例真实存在(避免无效ID导致错误):

from django.shortcuts import get_object_or_404

def add_manifest(request, reference_id):
    # 先获取对应的Orders实例,不存在则返回404
    order = get_object_or_404(Orders, id=reference_id)
    if request.method == "POST":
        form = CreateManifestForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('add_manifest', reference_id=reference_id)
    # 初始化表单时,将reference字段的默认值设为传入的reference_id
    form = CreateManifestForm(initial={'reference': reference_id})
    manifests = Manifests.objects.all()
    context = {
        'form': form,
        'reference_id': reference_id,
        'manifests' : manifests,
        'order': order,  # 可选,用于在模板显示订单的额外信息
    }
    return render(request, 'add_manifest.html', context)

2. 修改表单(forms.py):配置外键字段的显示方式

这里提供两种方案,根据你的需求选择:

方案A:隐藏字段(用户看不到该字段)

如果不需要用户看到reference_id,直接把字段设为隐藏:

class CreateManifestForm(forms.ModelForm):
    class Meta:
        model = Manifests
        fields = ('reference', 'cases', 'description', 'count')
        widgets = {
            'reference': forms.HiddenInput(),
        }

方案B:显示为只读文本(用户能看到但无法编辑)

如果需要用户看到reference_id但不能修改,用只读输入框:

class CreateManifestForm(forms.ModelForm):
    reference = forms.ModelChoiceField(
        queryset=Orders.objects.all(),
        widget=forms.TextInput(attrs={'readonly': 'readonly'})
    )
    class Meta:
        model = Manifests
        fields = ('reference', 'cases', 'description', 'count')

注意:不要用disabled属性,因为浏览器不会提交被标记为disabled的字段值,而readonly只会禁止编辑,依然会提交字段值。

3. 修改模板(add_manifest.html):正确渲染表单字段

现在不用自己写独立的input了,直接使用表单渲染的字段,这样能保证字段的name属性正确,后台能接收到值:

<div class="container">
    <form method="POST">
        <br>
        <br>
        {% csrf_token %}
        <div class="column">
            <label for="{{ form.reference.id_for_label }}">Reference ID: </label><br>
            <!-- 直接渲染表单的reference字段 -->
            {{ form.reference }}
            <!-- 如果你想显示纯文本而非输入框,可替换为下面的代码 -->
            <!-- {{ order.id }} <!-- 显示订单ID -->
            <!-- {{ form.reference.as_hidden }} <!-- 隐藏字段用于提交值 -->
        </div>
        <div class="column">
            <label for="{{ form.description.id_for_label }}">Description: </label>
            <br>
            {{ form.description}}
        </div>
        <div class="column">
            <label for="{{ form.cases.id_for_label }}">Cases: </label>
            <br>
            {{ form.cases }}
            <br>
        </div>
        <div class="column">
            <label for="{{ form.count.id_for_label }}">Count: </label>
            <br>
            {{ form.count }}
            <br>
            <br>
        </div>
        <br>
        <br>
        <button type="submit" name="add_mani" style="border-color: #7395AE;">Add Line</button>
    </form>
</div>

为什么原来的代码无法提交?

你之前自定义的<input type="text" value="{{ reference_id }}">没有设置name属性,表单提交时后台接收不到这个值;而且即使加了name,也没有和表单的reference字段关联,导致表单验证时reference字段(必填外键)缺失值,最终无法通过验证。

修改后,表单会正确初始化外键值,字段要么隐藏要么只读,提交时能传递正确的参数,验证通过后就能正常保存到数据库了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:04:34