如何根据父字段的值限制子字段的选择?

时间:2016-02-24 19:55:03

标签: python django

我有几个相当复杂的形式,依赖于模型层次结构来分配ForeignKey值。我需要根据父字段的值限制子字段的可用选择。问题是父字段的值可能来自绑定数据(POST请求)的初始数据(GET请求)。因此,我最终复制了这种模式:

class MyForm(forms.Form):
    parent = forms.ModelChoiceField(queryset=Parent.objects.all())
    child = forms.ModelChoiceField(queryset=Child.objects.all())

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)

        # Limit 'child' choices based on current value of 'parent'
        if self.is_bound and self.data.get('parent'):
            self.fields['child'].queryset = Child.objects.filter(parent__pk=self.data['parent'])
        elif self.initial.get('parent'):
            self.fields['child'].queryset = Child.objects.filter(parent=self.initial['parent'])
        else:
            self.fields['child'].choices = []

我感觉那里有一种更有效的方法来实现这一目标。我错过了什么?

3 个答案:

答案 0 :(得分:2)

你很幸运。 Django Smart Selects让这很简单!您必须使用ModelForm(如下所示)或使用ChainedForeignKey字段类型设置模型(如文档中所示)。

请注意 - 这不是确切的代码。提供的参数与您的模型定义和结构有关。但是,第一个选项看起来像这样:

from smart_selects.form_fields import ChainedModelChoiceField

class MyForm(forms.ModelForm):
    parent = forms.ModelChoiceField(queryset=Parent.objects.all())
    child = ChainedModelChoiceField('your_app','ModelName','parent','parent')
    class Meta:
        model = YourModel

您必须在呈现的页面中包含JQuery才能使用智能选择。呈现表单字段时,智能选择将包括适用的JQuery代码,以便在选择parent时发出Ajax请求,将children限制为与所选parent相关的选项。

答案 1 :(得分:0)

对于成千上万的儿童领域使用Ajax。

<强> urls.py

...
url(r'^api/toselect/(?P<parent_id>\d+)/$', views.toselect),
...

带有Childs的 views.py 响应json

...
from django.http import JsonResponse
...
def toselect(request, parent_id=0):
    objs = Child.objects.filter(parent_id=parent_id).values('id', 'name')
    return JsonResponse(list(objs), safe=False)

使用Jquery填充子项时选择父值更改

$("#id_parent").change(function(){
    var parentId = $("#id_parent").val()
    $.get( base_url + "api/toselect/"+parentId, function( data ) {
        $('#id_child').find('option').remove();

        $(data).each(function(i, v){
            $('#id_child').append('<option value="' + v.id + '">' + v.name+ '</option>');
        })
    });
});

答案 2 :(得分:-1)

生成两个包含所有值的选择字段。

style="border-spacing: 0; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;"

使用链式Jquery插件限制选项

<select id="id_country" name="country">
    <option value="" selected="selected">---------</option>
    <option value="1">Colombia</option>
    <option value="2">Rusia</option>
</select>
<select id="id_city" name="city">
    <option value="" selected="selected">---------</option>
    <option value="1" class="1">Bogotá</option>
    <option value="2" class="2">Moscú</option>
    <option value="3" class="2">San Petersburgo</option>
    <option value="4" class="1">Valledupar</option>
</select>

点击https://axiacore.com/blog/django-y-selects-encadenados/

中的完整帖子
相关问题