【问题标题】:Django model choice field - depend on other field's choiceDjango 模型选择字段 - 取决于其他字段的选择
【发布时间】:2014-08-17 09:12:06
【问题描述】:

我需要具有 2 个字段的 django modelform,其中第二个字段选择列表取决于第一个字段中选择的内容。我的模型:

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

如果 vehicle_type 设置为 personal,我如何将 make 字段的选项设置为 PERSONAL_MAKES?我怎样才能做到这一点?模型级别可以吗?

【问题讨论】:

    标签: python django django-models django-forms


    【解决方案1】:

    您可能不能,因为这取决于用户与您的表单的交互:您的服务器无法提前知道您的用户在将表单发送到浏览器之前会选择哪个元素。您可能可以使用 ajax 来实现这一点。我认为一个工作过程可能是:

    • 创建一个包含所有字段的表单,并将make字段设为hidden
    • 创建一个视图(我将其称为AjaxMakeFieldView),该视图将捕获采用vehicle_type 参数的ajax 请求并返回make field 的HTML,并填充相关数据。在您的 URLConf 中为此视图添加一个 URL。
    • 在您的模板中,添加 Javascript 绑定:当用户选择 vehicle_type 时,浏览器将向 AjaxMakeFieldView 发送 ajax 请求并将隐藏的 make 字段替换为返回的 HTML

    如果你不想要 javascript,另一种方法是两步形式:

    • 第一个带有vehicle_type 字段的表单
    • 提交第一个表单后,您的用户将获得第二个表单,其中包含 make 字段,初始数据根据在第一个表单中选择的 vehicle_type 填充。

    我从未这样做过,但Django documentation on Form wizard 似乎是一个不错的起点。

    【讨论】:

    • JS 解决方案很好,但我需要一些指导。我应该初始渲染什么?
    • 我编辑了我的答案。很抱歉没有提供代码示例,但我现在很忙。如果你没有达到你想要的,请告诉我,我会尽力提供更多细节。
    【解决方案2】:

    这就是我最终在一个页面上拥有两个相互依赖的模型选择字段的方式。在下面,field2 取决于 field1

    Javascript 部分

    请注意,在$.each() 中,不应使用$.parseJSON(resp)(而不仅仅是json),因为我们已经让jQuery 解析了它(由于 content_type='application/json' 响应) - 请参阅I keep getting "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')) - 然后可以使用obj.fielsd.&lt;myfieldname&gt; 在JQuery 中访问这些。

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

    【讨论】:

      【解决方案3】:

      另一种智能方法查询/免费且无需查看

      是为与field A选择相关的选项制作html标签。

      例如,在字段 B 选项中:

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

      此标记应与字段 A 值或文本相关。

      使用 JS 显示 block/none 相应地使用此选项标签。

      并且不要忘记每次用户更改字段 A 时重置值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-03
        • 2011-06-05
        • 2016-11-03
        • 2013-01-07
        • 1970-01-01
        • 2016-03-10
        • 2014-03-20
        • 2021-12-13
        相关资源
        最近更新 更多