Django模型选择字段 - 依赖其他字段的选择
我需要一个Django的模型表单,里面有两个字段,第二个字段的选项列表要根据第一个字段的选择来变化。我的模型是:
class Offer(BaseModel):
VEHICLE_TYPES = (
('personal','Personal car'),
('truck','Truck'),
)
vehicle_type = models.CharField(max_length=32, choices=VEHICLE_TYPES, default='personal', verbose_name='Vehicle type')
PERSONAL_MAKES = (
('',''),
)
TRUCK_MAKES = (
('',''),
)
make = models.CharField(max_length=32)#what more??
如果车辆类型设置为个人,我该如何把制造商字段的选项设置为个人制造商?我该怎么做?这能在模型层面实现吗?
3 个回答
另一种聪明的方法是查询/释放并且不需要视图。
就是为与字段A选择相关的选项制作HTML标签。
比如,在字段B的选项中:
<option example_tag="example_value" value="5"></option>
这个标签应该和字段A的值或文本有关。
可以使用JavaScript根据这个选项标签来显示或隐藏内容。
而且别忘了每次用户更改字段A时,要重置值。
这是我在一个页面上实现两个相互依赖的选择框的过程。在下面的例子中,field2
是依赖于 field1
的:
JavaScript 部分
注意,在 $.each()
中,不应该使用 $.parseJSON(resp)
(而是直接用 json
),因为我们已经通过 jQuery 解析过了(因为响应的内容类型是 'application/json') - 具体可以参考这个链接:我一直收到 "Uncaught SyntaxError: Unexpected token o"。
$(document).ready(function() {
$("#id_field2").empty();
$("#id_field1").change(function(){
$.ajax({
url: "{% url 'ajax_get_field_2' %}",
type: 'GET',
data: {field1_id: $("#id_field1").val()},
dataType: "json",
success: function(resp){
$("#id_field2").empty();
$.each(resp, function(idx, obj) {
$('#id_field2').append($('<option></option>').attr('value', obj.pk).text(obj.fields.code + ' (' + obj.fields.affection + ')'));
});
},
error: function(jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
});
Django views.py 部分
注意,这个功能可能也可以通过 django-rest-framework 来实现。
我从我的 MyModel2
中获取 fields=('id', 'code', 'affection'))
- 然后可以在 jQuery 中通过 obj.fields.<myfieldname>
来访问这些字段。
class AjaxField2View(generic.View):
def get(self, request, *args, **kwargs):
field_1 = get_object_or_404(MyModel1, pk=request.GET.get('field1_id', ''))
model2_results = MyModel2.objects.filter(k_value=field_1 .k_value)
return HttpResponse(serializers.serialize('json', model2_results, fields=('id', 'code', 'affection')), content_type='application/json')
你可能做不到,因为这取决于用户和你表单的互动:你的服务器无法提前知道用户会选择哪个选项,然后再把表单发送到浏览器。你可以考虑使用ajax来实现这个功能。我觉得一个可行的流程可以是:
- 创建一个包含所有字段的表单,并把
make
字段设置为隐藏 - 创建一个视图(我称之为
AjaxMakeFieldView
),这个视图会接收一个ajax请求,参数是vehicle_type
,并返回make field
的HTML,里面填充相关数据。为这个视图在你的URL配置中添加一个URL。 - 在你的模板中,添加一个JavaScript绑定:当用户选择一个
vehicle_type
时,浏览器会向AjaxMakeFieldView
发送一个ajax请求,并用返回的HTML替换掉隐藏的make
字段。
如果你不想用JavaScript,另一种方法是使用两步表单:
- 第一个表单包含一个
vehicle_type
字段。 - 当第一个表单提交后,用户会看到第二个表单,里面有一个
make
字段,初始数据会根据第一个表单中选择的vehicle_type
来填充。
我自己没有做过这个,但Django文档中的表单向导似乎是一个不错的起点。