Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何基于父字段限制子字段的选择';s值多少?_Python_Django - Fatal编程技术网

Python 如何基于父字段限制子字段的选择';s值多少?

Python 如何基于父字段限制子字段的选择';s值多少?,python,django,Python,Django,我有几个相当复杂的表单,它们依赖于模型层次结构来分配ForeignKey值。我需要根据父字段的值限制子字段可用的选项。问题是父字段的值可能来自初始数据(GET请求)或绑定数据(POST请求)。因此,我最终大量复制了这种模式: class MyForm(forms.Form): parent = forms.ModelChoiceField(queryset=Parent.objects.all()) child = forms.ModelChoiceField(queryset=

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

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 = []
我觉得有一种更有效的方法来实现这一点。我错过了什么?

你很幸运。让这变得非常简单!您必须使用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代码,以便在选择
父项
时发出Ajax请求,将
子项
限制为与所选
父项
相关的选项,生成两个包含所有值的选择字段

<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>

里德在

中的完整文章中为成千上万的子字段使用Ajax

url.py

...
url(r'^api/toselect/(?P<parent_id>\d+)/$', views.toselect),
...
使用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>');
        })
    });
});
$(“#id_父项”)。更改(函数(){
var parentId=$(“#id_parent”).val()
$.get(base_url+“api/toselect/”+parentId,函数(数据){
$('#id_child')。查找('option')。删除();
$(数据)。每个功能(i、v){
$('id_child')。附加(''+v.name+'');
})
});
});

不幸的是,在呈现表单之前,必须过滤父字段的查询集。否则,子字段可能有数千个选项,这显然会导致性能问题。数千个选项会导致性能问题。在这种情况下,您应该使用ajax
...
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)
$("#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>');
        })
    });
});