summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-02-12 17:08:03 +0100
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-02-13 15:57:56 +0100
commit65113401f1f6786f8a89dfcb7d0347924b317e7b (patch)
treeaaa7ec1761578ec558495f8d61c72def1e56badb
parent861f9a2427ffbfee2a33cda5ed6a2047916fcfcb (diff)
[5.1.x] Fixed #36182 -- Returned "?" if all parameters are removed in querystring template tag.
Thank you to David Feeley for the report and Natalia Bidart for the review. Backport of 05002c153c5018e4429a326a6699c7c45e5ea957 from main.
-rw-r--r--django/template/defaulttags.py14
-rw-r--r--docs/ref/templates/builtins.txt2
-rw-r--r--docs/releases/5.1.7.txt4
-rw-r--r--tests/template_tests/syntax_tests/test_querystring.py9
4 files changed, 20 insertions, 9 deletions
diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py
index ae74679ec6..1152452081 100644
--- a/django/template/defaulttags.py
+++ b/django/template/defaulttags.py
@@ -1194,18 +1194,18 @@ def querystring(context, query_dict=None, **kwargs):
"""
if query_dict is None:
query_dict = context.request.GET
- query_dict = query_dict.copy()
+ params = query_dict.copy()
for key, value in kwargs.items():
if value is None:
- if key in query_dict:
- del query_dict[key]
+ if key in params:
+ del params[key]
elif isinstance(value, Iterable) and not isinstance(value, str):
- query_dict.setlist(key, value)
+ params.setlist(key, value)
else:
- query_dict[key] = value
- if not query_dict:
+ params[key] = value
+ if not params and not query_dict:
return ""
- query_string = query_dict.urlencode()
+ query_string = params.urlencode()
return f"?{query_string}"
diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
index c00baf3a07..7d2cf93085 100644
--- a/docs/ref/templates/builtins.txt
+++ b/docs/ref/templates/builtins.txt
@@ -965,7 +965,7 @@ This tag requires a :class:`~django.http.QueryDict` instance, which defaults to
:attr:`request.GET <django.http.HttpRequest.GET>` if none is provided.
If the :class:`~django.http.QueryDict` is empty and no additional parameters
-are provided, an empty string is returned. A non-empty result includes a
+are provided, an empty string is returned. Otherwise, the result includes a
leading ``"?"``.
.. admonition:: Using ``request.GET`` as default
diff --git a/docs/releases/5.1.7.txt b/docs/releases/5.1.7.txt
index 8143305a96..e184da6aca 100644
--- a/docs/releases/5.1.7.txt
+++ b/docs/releases/5.1.7.txt
@@ -9,4 +9,6 @@ Django 5.1.7 fixes several bugs in 5.1.6.
Bugfixes
========
-* ...
+* Fixed a bug in Django 5.1 where the ``{% querystring %}`` template tag
+ returned an empty string rather than ``"?"`` when all parameters had been
+ removed from the query string (:ticket:`36182`).
diff --git a/tests/template_tests/syntax_tests/test_querystring.py b/tests/template_tests/syntax_tests/test_querystring.py
index 3f1cf3d281..099be96f9e 100644
--- a/tests/template_tests/syntax_tests/test_querystring.py
+++ b/tests/template_tests/syntax_tests/test_querystring.py
@@ -17,6 +17,15 @@ class QueryStringTagTests(SimpleTestCase):
output = template.render(context)
self.assertEqual(output, "")
+ @setup({"test_querystring_remove_all_params": "{% querystring a=None %}"})
+ def test_querystring_remove_all_params(self):
+ non_empty_context = RequestContext(self.request_factory.get("/?a=b"))
+ empty_context = RequestContext(self.request_factory.get("/"))
+ template = self.engine.get_template("test_querystring_remove_all_params")
+ for context, expected in [(non_empty_context, "?"), (empty_context, "")]:
+ with self.subTest(expected=expected):
+ self.assertEqual(template.render(context), expected)
+
@setup({"querystring_non_empty": "{% querystring %}"})
def test_querystring_non_empty(self):
request = self.request_factory.get("/", {"a": "b"})