Fixed #11629 -- Deprecated callable arguments to queryset methods.

Callable arguments were an untested and undocumented feature.
This commit is contained in:
Baptiste Mispelon 2013-12-18 16:59:08 +01:00
parent d34c8c338a
commit f1b3ab9c21
4 changed files with 29 additions and 0 deletions

View File

@ -9,6 +9,7 @@ all about the internals of models in order to get the information it needs.
from collections import OrderedDict from collections import OrderedDict
import copy import copy
import warnings
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.tree import Node from django.utils.tree import Node
@ -1036,6 +1037,9 @@ class Query(object):
lookup_type = 'isnull' lookup_type = 'isnull'
value = True value = True
elif callable(value): elif callable(value):
warnings.warn(
"Passing callable arguments to queryset is deprecated.",
PendingDeprecationWarning, stacklevel=2)
value = value() value = value()
elif isinstance(value, ExpressionNode): elif isinstance(value, ExpressionNode):
# If value is a query expression, evaluate it # If value is a query expression, evaluate it

View File

@ -226,6 +226,8 @@ these changes.
loading APIs instead. Several undocumented methods of the ``AppCache`` class loading APIs instead. Several undocumented methods of the ``AppCache`` class
will also be removed. will also be removed.
* Passing callable arguments to querysets will no longer be possible.
2.0 2.0
--- ---

View File

@ -869,3 +869,14 @@ Geo Sitemaps
Google has retired support for the Geo Sitemaps format. Hence Django support Google has retired support for the Geo Sitemaps format. Hence Django support
for Geo Sitemaps is deprecated and will be removed in Django 1.8. for Geo Sitemaps is deprecated and will be removed in Django 1.8.
Passing callable arguments to queryset methods
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Callable arguments for querysets were an undocumented feature that was
unreliable. It's been deprecated and will be removed in Django 1.9.
Callable arguments were evaluated when a queryset was constructed rather than
when it was evaluated, thus this feature didn't offer any benefit compared to
evaluating arguments before passing them to queryset and created confusion that
the arguments may have been evaluated at query time.

View File

@ -5,6 +5,7 @@ import datetime
from operator import attrgetter from operator import attrgetter
import pickle import pickle
import unittest import unittest
import warnings
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db import DatabaseError, connection, connections, DEFAULT_DB_ALIAS from django.db import DatabaseError, connection, connections, DEFAULT_DB_ALIAS
@ -1139,6 +1140,17 @@ class Queries1Tests(BaseQuerysetTest):
['<Author: a1>', '<Author: a2>', '<Author: a3>', '<Author: a4>'] ['<Author: a1>', '<Author: a2>', '<Author: a3>', '<Author: a4>']
) )
def test_callable_args(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
qs = Tag.objects.filter(name__startswith=lambda: 't')
self.assertQuerysetEqual(
qs,
['<Tag: t1>', '<Tag: t2>', '<Tag: t3>', '<Tag: t4>', '<Tag: t5>']
)
self.assertEqual(len(w), 1)
self.assertTrue(issubclass(w[0].category, PendingDeprecationWarning))
class Queries2Tests(TestCase): class Queries2Tests(TestCase):
def setUp(self): def setUp(self):