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 技能并且遇到类似问题的人。我部署了这个解决方案并且它有效,但如果有人发现问题,请告诉我:-)
我会尽可能详细地公开我的案例:
我正在使用自动完成功能自动将动态值填充到表单中。该表单有多个值,当您填写前 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 技能并且遇到类似问题的人。我部署了这个解决方案并且它有效,但如果有人发现问题,请告诉我:-)