summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Lyabah <a.lyabah@checkio.org>2020-11-28 18:08:27 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2021-01-05 10:37:11 +0100
commit415f50298f97fb17f841a9df38d995ccf347dfcc (patch)
tree3907c7f089deaae35a4d1f96e1208ba2e79e8aa1
parentaa3d36063174cc1e16a1e5150b6b47609dd1e79a (diff)
Fixed #32231 -- Allowed passing None params to QuerySet.raw().
-rw-r--r--django/db/models/query.py6
-rw-r--r--django/db/models/sql/query.py10
-rw-r--r--docs/ref/models/querysets.txt7
-rw-r--r--docs/topics/db/sql.txt7
-rw-r--r--tests/raw_query/tests.py5
5 files changed, 28 insertions, 7 deletions
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 9dc98c02d1..32fee78e9f 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -818,7 +818,7 @@ class QuerySet:
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
##################################################
- def raw(self, raw_query, params=None, translations=None, using=None):
+ def raw(self, raw_query, params=(), translations=None, using=None):
if using is None:
using = self.db
qs = RawQuerySet(raw_query, model=self.model, params=params, translations=translations, using=using)
@@ -1419,14 +1419,14 @@ class RawQuerySet:
Provide an iterator which converts the results of raw SQL queries into
annotated model instances.
"""
- def __init__(self, raw_query, model=None, query=None, params=None,
+ def __init__(self, raw_query, model=None, query=None, params=(),
translations=None, using=None, hints=None):
self.raw_query = raw_query
self.model = model
self._db = using
self._hints = hints or {}
self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params)
- self.params = params or ()
+ self.params = params
self.translations = translations or {}
self._result_cache = None
self._prefetch_related_lookups = ()
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 93cc32ac3c..a39430b28d 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -69,8 +69,8 @@ JoinInfo = namedtuple(
class RawQuery:
"""A single raw SQL query."""
- def __init__(self, sql, using, params=None):
- self.params = params or ()
+ def __init__(self, sql, using, params=()):
+ self.params = params
self.sql = sql
self.using = using
self.cursor = None
@@ -111,9 +111,13 @@ class RawQuery:
@property
def params_type(self):
+ if self.params is None:
+ return None
return dict if isinstance(self.params, Mapping) else tuple
def __str__(self):
+ if self.params_type is None:
+ return self.sql
return self.sql % self.params_type(self.params)
def _execute_query(self):
@@ -127,6 +131,8 @@ class RawQuery:
params = tuple(adapter(val) for val in self.params)
elif params_type is dict:
params = {key: adapter(val) for key, val in self.params.items()}
+ elif params_type is None:
+ params = None
else:
raise RuntimeError("Unexpected params type: %s" % params_type)
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 70a6989306..2c8c2e38fd 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -1843,7 +1843,7 @@ raised if ``select_for_update()`` is used in autocommit mode.
``raw()``
~~~~~~~~~
-.. method:: raw(raw_query, params=None, translations=None)
+.. method:: raw(raw_query, params=(), translations=None)
Takes a raw SQL query, executes it, and returns a
``django.db.models.query.RawQuerySet`` instance. This ``RawQuerySet`` instance
@@ -1858,6 +1858,11 @@ See the :doc:`/topics/db/sql` for more information.
filtering. As such, it should generally be called from the ``Manager`` or
from a fresh ``QuerySet`` instance.
+.. versionchanged:: 3.2
+
+ The default value of the ``params`` argument was changed from ``None`` to
+ an empty tuple.
+
Operators that return new ``QuerySet``\s
----------------------------------------
diff --git a/docs/topics/db/sql.txt b/docs/topics/db/sql.txt
index c7224c78b0..fe7b0a4bd8 100644
--- a/docs/topics/db/sql.txt
+++ b/docs/topics/db/sql.txt
@@ -43,7 +43,7 @@ Performing raw queries
The ``raw()`` manager method can be used to perform raw SQL queries that
return model instances:
-.. method:: Manager.raw(raw_query, params=None, translations=None)
+.. method:: Manager.raw(raw_query, params=(), translations=None)
This method takes a raw SQL query, executes it, and returns a
``django.db.models.query.RawQuerySet`` instance. This ``RawQuerySet`` instance
@@ -99,6 +99,11 @@ make it very powerful.
both rows will match. To prevent this, perform the correct typecasting
before using the value in a query.
+.. versionchanged:: 3.2
+
+ The default value of the ``params`` argument was changed from ``None`` to
+ an empty tuple.
+
Mapping query fields to model fields
------------------------------------
diff --git a/tests/raw_query/tests.py b/tests/raw_query/tests.py
index 17a5a68a8a..cf57cfd696 100644
--- a/tests/raw_query/tests.py
+++ b/tests/raw_query/tests.py
@@ -180,6 +180,11 @@ class RawQueryTests(TestCase):
self.assertEqual(len(results), 1)
self.assertIsInstance(repr(qset), str)
+ def test_params_none(self):
+ query = "SELECT * FROM raw_query_author WHERE first_name like 'J%'"
+ qset = Author.objects.raw(query, params=None)
+ self.assertEqual(len(qset), 2)
+
def test_escaped_percent(self):
query = "SELECT * FROM raw_query_author WHERE first_name like 'J%%'"
qset = Author.objects.raw(query)