【问题标题】:Update field in rendered Django Form更新渲染的 Django 表单中的字段
【发布时间】:2018-07-07 14:34:42
【问题描述】:

我很难弄清楚如何在编辑表单时更新 Django 表单中的字段。

在我的表单中,我有一个 ModelChoiceField 和 ChoiceField:第一个是汽车制造商列表,第二个是该制造商可用的模型列表。显然,我不想在第二个字段中为每个制造商填写模型,而只想为在第一个 ModelChoiceField 中选择的一个。

这是我的示例表单:

class PostForm(forms.ModelForm):
    make = forms.ModelChoiceField(queryset=Manufacturer.objects.all())
    model = forms.ChoiceField()
    ...

为了呈现模板,我使用基于类的视图:

class CreatePost(View):
    template_name = 'post/edit_post.html'

def get(self, request):
    form = PostForm()
    return render(request, self.template_name, {'form': form})

def post(self, request):
    form = PostForm(request.POST)

    if form.is_valid():
        post = form.save(commit=False)
        post.owner = request.user
        post.save()
        return redirect('homepage')

    return render(request, self.template_name, {'form': form})

在我渲染PostForm 后的模板中,我使用jQuery 禁用model 字段并等待用户在make 字段中选择一些值。这是我的模板:

<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
      {% csrf_token %}
      {{ form.non_field_errors }}
      {% for field in form %}
           <div class="form-group">
             <label class="control-label">{{ field.label_tag }}</label>
             {{ field }}
             {{ field.errors }}
           </div>
           <div class="form-group">
              <button type="submit" class="btn btn-default">Submit</button>
           </div>
      {% endfor %}      
</form>

然后使用AJAX 请求model 字段的值(在此示例代码中,我只返回单个项目):

$('#id_make').change(function () {
        $.ajax({
            url: '{% url 'get_models' %}',
            data: {'make': $('#id_make :selected').text()},
            dataType: 'json',
            success: function (data) {
                $('#id_model').append($('<option>', {
                    value: 1,
                    text: data.model})).removeAttr('disabled');
                }
            });
        })

这是我用来处理 AJAX 调用的视图(出于显示目的并在这个问题中保持简单,我在 modelsSeries 中只有一条记录,每个 manufacturer 知道这一点我只查询一条记录。series 是 CharField,它保留了 model 的标题,例如 'Mitsubishi' 制造商的 'Lancer'。):

def get_models(request):
    manufacturer = Manufacturer.objects.get(make=request.GET.get('make'))
    model = Series.objects.get(make_fk= manufacturer)
    return JsonResponse({'model': model.series})

完成此操作后,我确实在model ChoiceField&lt;select&gt; 元素中看到了更新的选项,但是在我在model ChoiceField 中选择新值并提交表单后,我收到了:

Select a valid choice. 1 is not one of the available choices."
  • '1'是我附加到&lt;select&gt;元素然后提交的元素的id。

然后我深入挖掘并打印了提交的表单的内容,看起来虽然我看到模板中更新了&lt;select&gt; 元素,但它在我提交的表单中保持空白:

<select name="model" class="form-control" id="id_model"></select>

为什么会发生这种情况以及如何更新表单字段本身而不仅仅是 &lt;select&gt; 元素?

【问题讨论】:

  • 能否分享一下您的模板表单代码?
  • @TheCoder 照你说的做了
  • 嗯..谢谢!能否请您也添加查看部分代码?
  • @TheCoder 为 AJAX 调用添加了视图,您还想查看呈现模板的视图类吗?这很标准。
  • 是的,分享 View Class 代码会很有帮助!

标签: jquery ajax django forms


【解决方案1】:

目前,您还没有设置任何model 选项,所以它永远不会有效。您可以覆盖 __init__ 方法并在那里设置选项。

您可以将选项设置为所有型号,然后在clean 方法中验证型号是否与品牌匹配。

class PostForm(forms.ModelForm):
    make = forms.ModelChoiceField(queryset=Manufacturer.objects.all())
    model = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super(PostForm, self).__init__(*args, **kwargs)
        if self.data:
            self.fields['model'].choices = ...

    def clean(self)
        # check that model matches make

由于model 字段引用series 模型,使用ModelChoiceField 并设置self.fields['model'].queryset 可能更容易。

这只是我脑海中的一个粗略想法。 tutorial you found 使用了类似的方法,但完整且解释更详细。

【讨论】:

  • 感谢您的输入,但如果我正确理解您的回答,您建议使用所有制造商的所有型号填充“ChoiceField”,然后检查用户是否在 clean() 中选择了匹配的品牌和型号方法?如果这不是你的意思,请纠正我,但如果是 - 这正是我试图避免的那种流程。
  • 或者你的意思是将所有制造商的所有模型加载到“ModelChoiceField”,在模板加载后隐藏所有内容并像以前一样使用 Ajax 请求从头开始填充
  • 关键是您只填充 POST 请求的选项(当 self.data 评估为 True 时)。对于初始的GET 请求,选项仍然为空,并使用 ajax 填充到模板中。您链接到的教程采用相同的方法,但它在 __init__ 方法中过滤查询集,因此不需要 clean。使用ModelChoiceField() 的建议是完全独立的
【解决方案2】:

我找到了带有代码示例的解释解决方案,如何实现链接/依赖下拉菜单,巧合的是,该解决方案是在我发布此问题后立即发布的。

Here's a link.

【讨论】:

    猜你喜欢
    • 2012-02-25
    • 2020-04-25
    • 2021-06-07
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 2015-04-14
    • 1970-01-01
    相关资源
    最近更新 更多