Django模型选择字段 - 依赖其他字段的选择

14 投票
3 回答
12471 浏览
提问于 2025-04-18 11:11

我需要一个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 个回答

0

另一种聪明的方法是查询/释放并且不需要视图

就是为与字段A选择相关的选项制作HTML标签。

比如,在字段B的选项中:

<option example_tag="example_value" value="5"></option>

这个标签应该和字段A的值或文本有关。

可以使用JavaScript根据这个选项标签来显示或隐藏内容。

而且别忘了每次用户更改字段A时,要重置值。

0

这是我在一个页面上实现两个相互依赖的选择框的过程。在下面的例子中,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')
5

你可能做不到,因为这取决于用户和你表单的互动:你的服务器无法提前知道用户会选择哪个选项,然后再把表单发送到浏览器。你可以考虑使用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文档中的表单向导似乎是一个不错的起点。

撰写回答