Merge pull request #38158 from kaulith/fix/in-filter-comma-in-value
fix(filter): use JSON encoding for in filter values containing commas
This commit is contained in:
commit
3a8a93a168
4 changed files with 47 additions and 4 deletions
|
|
@ -888,7 +888,11 @@ from {tables}
|
|||
if value is None:
|
||||
values = f.value or ""
|
||||
if isinstance(values, str):
|
||||
values = values.split(",")
|
||||
try:
|
||||
parsed = json.loads(values)
|
||||
values = parsed if isinstance(parsed, list) else [parsed]
|
||||
except ValueError:
|
||||
values = values.split(",")
|
||||
|
||||
fallback = "''"
|
||||
value = [frappe.db.escape((cstr(v) or "").strip(), percent=False) for v in values]
|
||||
|
|
|
|||
|
|
@ -203,7 +203,9 @@ frappe.ui.Filter = class {
|
|||
this._filter_value_set = Promise.resolve();
|
||||
|
||||
if (["in", "not in"].includes(condition) && Array.isArray(value)) {
|
||||
value = value.join(",");
|
||||
value = value.some((v) => String(v).includes(","))
|
||||
? JSON.stringify(value)
|
||||
: value.join(",");
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
|
|
@ -485,7 +487,12 @@ frappe.ui.filter_utils = {
|
|||
}
|
||||
} else if (["in", "not in"].includes(condition)) {
|
||||
if (val) {
|
||||
val = val.split(",").map((v) => strip(v));
|
||||
try {
|
||||
const parsed = JSON.parse(val);
|
||||
val = Array.isArray(parsed) ? parsed : [String(parsed)];
|
||||
} catch {
|
||||
val = val.split(",").map((v) => strip(v));
|
||||
}
|
||||
}
|
||||
} else if (frappe.boot.additional_filters_config[condition]) {
|
||||
val = field.value || val;
|
||||
|
|
|
|||
|
|
@ -271,6 +271,33 @@ class TestDBQuery(IntegrationTestCase):
|
|||
result in DatabaseQuery("DocType").execute(filters={"name": ["not in", "DocType,DocField"]})
|
||||
)
|
||||
|
||||
def test_in_filter_json_encoded_values(self):
|
||||
# JSON-encoded list string should work the same as comma-separated
|
||||
for result in [{"name": "DocType"}, {"name": "DocField"}]:
|
||||
self.assertTrue(
|
||||
result
|
||||
in DatabaseQuery("DocType").execute(filters={"name": ["in", '["DocType", "DocField"]']})
|
||||
)
|
||||
|
||||
# Values containing commas must not be split
|
||||
todo = frappe.get_doc(
|
||||
doctype="ToDo", description="Test, With Comma", allocated_to="Administrator"
|
||||
).insert()
|
||||
try:
|
||||
results = DatabaseQuery("ToDo").execute(
|
||||
filters={"description": ["in", '["Test, With Comma"]']},
|
||||
fields=["description"],
|
||||
)
|
||||
self.assertIn({"description": "Test, With Comma"}, results)
|
||||
|
||||
results_split = DatabaseQuery("ToDo").execute(
|
||||
filters={"description": ["in", "Test, With Comma"]},
|
||||
fields=["description"],
|
||||
)
|
||||
self.assertNotIn({"description": "Test, With Comma"}, results_split)
|
||||
finally:
|
||||
frappe.delete_doc("ToDo", todo.name)
|
||||
|
||||
def test_string_as_field(self):
|
||||
self.assertEqual(
|
||||
frappe.get_all("DocType", as_list=True), frappe.get_all("DocType", fields="name", as_list=True)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
import textwrap
|
||||
from collections import defaultdict
|
||||
from collections.abc import Generator, Iterable, Mapping, Sequence
|
||||
|
|
@ -110,7 +111,11 @@ class FilterTuple(_FilterTuple):
|
|||
|
||||
# soundness
|
||||
if operator in ("in", "not in") and isinstance(value, str):
|
||||
value = value.split(",")
|
||||
try:
|
||||
parsed = json.loads(value)
|
||||
value = parsed if isinstance(parsed, list) else value.split(",") # type: ignore[assignment]
|
||||
except ValueError:
|
||||
value = value.split(",")
|
||||
|
||||
_value: Value
|
||||
if isinstance(value, _InputValue):
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue