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>');
})
});
});