Select2ListView 中的自由文本 django-autocomplete-light

Free text in Select2ListView django-autocomplete-light

我会尽可能详细地公开我的案例:

我正在使用自动完成功能自动将动态值填充到表单中。该表单有多个值,当您填写前 3 个值时,我可以 运行 一个操作(使用这些值)并 return 向用户建议一个值。 我需要稍微调整一下 return 参数,但我使用 Select2ListView

实现了它
class MyFunctionAutocomplete(autocomplete.Select2ListView):
    def get_list(self):
        if not self.request.user.is_authenticated:
            return [""]
        try:
            field1_pk = self.forwarded["field1"]
            field2_pk = self.forwarded["field2"]
            field3_pk = self.forwarded["field3"]
        except AttributeError:
            return [""]
        try:
            ObjField1 = ModelField1.objects.get(pk=field1_pk)
            ObjField2 = ModelField2.objects.get(pk=field2_pk)
            ObjField3 = ModelField3.objects.get(pk=field3_pk)
            return_value = ObjField1.get_result(param1=ObjField2, param2=ObjField3)
        except (ModelField1.DoesNotExist, ModelField2.DoesNotExist, ModelField3.DoesNotExist):
            return [""]
        return [return_value]

使用此代码,我可以在存在要求(转发值)时执行我需要的操作。到目前为止,还不错

我的问题: 我不能添加任何值作为额外选项。这个值不是 ForeignKey,它是一个简单的 Float。我希望用户能够使用我建议的值,或者只是用他们选择的另一个值替换它。假设在下拉列表中他们的值为 3.22221,他们想写 12.11.

因为它实际上可以是任何值,所以我认为自由文本是有意义的(如有必要,我稍后会负责清理数据)。我检查了一下,看起来 https://select2.org/tagging 是我想要的,但不确定我是否可以在这里使用它。

如果有帮助,我在表单中的表单字段如下:

result_field = Select2ListCreateChoiceField(
        widget=autocomplete.Select2(
            url="myapp:result_field_autocomplete",
            forward=["field1", "field2", "field3"],
            attrs={"data-container-css-class": ""},
        ),
        help_text=constants.RESULT_HELP,
)

所需功能:

result_field = Select2ListCreateChoiceField(
        widget=autocomplete.Select2(
            url="myapp:result_field_autocomplete",
            forward=["field1", "field2", "field3"],
            attrs={"data-container-css-class": ""},
            **free_text=True,**
        ),
        help_text=constants.RESULT_HELP,
)

并且该标志将允许我输入我选择的任何文本。

我可以通过将小部件更改为 TaggingSelect2 来到达某个地方,但可以肯定的是,这不是选项,很笨拙,用户将有多个选项,这不是我想要的。

理想情况下,我所需要的(如果有人能想到另一个选项)是在我通过 运行ning 该函数填充其他 3 个元素后作为初始数据出现在表单中的信息。如果能用另一种方法做到这一点,那就太好了。

我希望它有意义:)

万一有人发现同样的问题,我在 Javascript 方面的经验非常有限,但我在拥有一个按钮和创建一个调用视图的 Javascript 函数方面做出了妥协(与 django 的方式相同-autocomplete-light 确实如此):

最终代码:

urls.py:

path(
    "result-autocomplete/",
    views.MyFunctionAutocomplete,
    name="result_autocomplete",
),

views.py:

def MyFunctionAutocomplete(request):
    if not request.user.is_authenticated:
        return HttpResponse("")
    try:
        field1 = request.GET["field1"]
        field2 = request.GET["field2"]
        field3_name = request.GET["field3"]
        obj_Field3 = ModelField3.objects.get(name=field3_name)
    except AttributeError:
        return HttpResponse("")
    except ModelField3.DoesNotExist:
        return HttpResponse("")

    current_result = obj_Field3.get_result(f"{field1}{field2}")
    return HttpResponse(current_result["result"])

getresult.js:

function getResult(url){
 var field1 = document.querySelector('[id=select2-id_field1-container]').innerText
 var field2 = document.querySelector('[id=select2-id_field2-container]').innerText
 var field3_name = document.querySelector("#id_field3").selectedOptions[0].innerHTML
 if ( field1 && field2 && field3_name){
   $.ajax({                       // initialize an AJAX request
    url: url,
    data: {
      'field1': field1,       // add the field1 to the GET parameters
      'field2': field2,           // add the field2 to the GET parameters
      'field3_name': field3_name    // add the field3_name to the GET parameters
    },
    success: function (data) {   // `data` is the return of the `MyFunctionAutocomplete` view function
      $("#id_result")[0].value = data ;  // replace the contents of the price input with the data that came from the server
      $("#id_result")[0].placeholder = data // Not needed really
    }
  });
 }
}

django-template.html:

[...]
      <form method="post">
        {% csrf_token %}
      {% for field in form %}
        {% if field.name == "result" %}
          <script defer src="{% static 'js/getresult.js' %}"></script>
          <button type="button" id="getresult" onclick="getresult('{% url "result_autocomplete"%}')">Get live result</button>
          {% bootstrap_field field show_label=True label_class="result" %}
        {% else %}
          {% bootstrap_field field %}
        {% endif %}
      {% endfor %}
[...]

我希望这能帮助其他像我一样没有很好的 JS 技能并且遇到类似问题的人。我部署了这个解决方案并且它有效,但如果有人发现问题,请告诉我:-)