mirror of
https://github.com/django/django.git
synced 2024-11-18 15:34:16 +00:00
20bab2cf9d
Allowed users to specify which lookups or transforms ("nested lookus") are available for fields. The implementation is now class based. Squashed commit of the following: commitfa7a7195f1
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 18 10:53:24 2014 +0200 Added lookup registration API docs commiteb1c8ce164
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Tue Jan 14 18:59:36 2014 +0200 Release notes and other minor docs changes commit11501c29c9
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Jan 12 20:53:03 2014 +0200 Forgot to add custom_lookups tests in prev commit commit83173b960e
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Jan 12 19:59:12 2014 +0200 Renamed Extract -> Transform commit3b18d9f3a1
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Jan 12 19:51:53 2014 +0200 Removed suggestion of temporary lookup registration from docs commit21d0c7631c
Merge:2509006
f2dc442
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Jan 12 09:38:23 2014 -0800 Merge pull request #2 from mjtamlyn/lookups_3 Reworked custom lookups docs. commitf2dc4429a1
Author: Marc Tamlyn <marc.tamlyn@gmail.com> Date: Sun Jan 12 13:15:05 2014 +0000 Reworked custom lookups docs. Mostly just formatting and rewording, but also replaced the example using ``YearExtract`` to use an example which is unlikely to ever be possible directly in the ORM. commit2509006506
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Jan 12 13:19:13 2014 +0200 Removed unused import commit4fba5dfaa0
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 11 22:34:41 2014 +0200 Added docs to index commit6d53963f37
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 11 22:10:24 2014 +0200 Dead code removal commitf9cc039007
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 11 19:00:43 2014 +0200 A new try for docs commit33aa18a6e3
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 11 14:57:12 2014 +0200 Renamed get_cols to get_group_by_cols commitc7d5f8661b
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 11 14:45:53 2014 +0200 Altered query string customization for backends vendors The new way is trying to call first method 'as_' + connection.vendor. If that doesn't exist, then call as_sql(). Also altered how lookup registration is done. There is now RegisterLookupMixin class that is used by Field, Extract and sql.Aggregate. This allows one to register lookups for extracts and aggregates in the same way lookup registration is done for fields. commit90e7004ec1
Merge:66649ff
f7c2c0a
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 11 13:21:01 2014 +0200 Merge branch 'master' into lookups_3 commit66649ff891
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Jan 11 13:16:01 2014 +0200 Some rewording in docs commit31b8faa627
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Dec 29 15:52:29 2013 +0200 Cleanup based on review comments commit1016159f34
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Dec 28 18:37:04 2013 +0200 Proof-of-concept fix for #16731 Implemented only for SQLite and PostgreSQL, and only for startswith and istartswith lookups. commit193cd097ca
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Dec 28 17:57:58 2013 +0200 Fixed #11722 -- iexact=F() produced invalid SQL commit08ed3c3b49
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Dec 21 23:59:52 2013 +0200 Made Lookup and Extract available from django.db.models commitb99c8d83c9
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Dec 21 23:06:29 2013 +0200 Fixed review notes by Loic commit049eebc070
Merge:ed8fab7
b80a835
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Dec 21 22:53:10 2013 +0200 Merge branch 'master' into lookups_3 Conflicts: django/db/models/fields/__init__.py django/db/models/sql/compiler.py django/db/models/sql/query.py tests/null_queries/tests.py commited8fab7fe8
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Dec 21 22:47:23 2013 +0200 Made Extracts aware of full lookup path commit27a57b7aed
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Dec 1 21:10:11 2013 +0200 Removed debugger import commit074e0f5aca
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Dec 1 21:02:16 2013 +0200 GIS lookup support added commit760e28e72b
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Dec 1 20:04:31 2013 +0200 Removed usage of Constraint, used Lookup instead commiteac4776684
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Dec 1 02:22:30 2013 +0200 Minor cleanup of Lookup API commit2adf50428d
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sun Dec 1 02:14:19 2013 +0200 Added documentation, polished implementation commit32c04357a8
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Nov 30 23:10:15 2013 +0200 Avoid OrderedDict creation on lookup aggregate check commit7c8b3a32cc
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Sat Nov 30 23:04:34 2013 +0200 Implemented nested lookups But there is no support of using lookups outside filtering yet. commit4d219d4cde
Author: Anssi Kääriäinen <akaariai@gmail.com> Date: Wed Nov 27 22:07:30 2013 +0200 Initial implementation of custom lookups
85 lines
2.9 KiB
Python
85 lines
2.9 KiB
Python
from __future__ import unicode_literals
|
|
|
|
from django.test import TestCase
|
|
from django.core.exceptions import FieldError
|
|
|
|
from .models import Poll, Choice, OuterA, Inner, OuterB
|
|
|
|
|
|
class NullQueriesTests(TestCase):
|
|
|
|
def test_none_as_null(self):
|
|
"""
|
|
Regression test for the use of None as a query value.
|
|
|
|
None is interpreted as an SQL NULL, but only in __exact and __iexact
|
|
queries.
|
|
Set up some initial polls and choices
|
|
"""
|
|
p1 = Poll(question='Why?')
|
|
p1.save()
|
|
c1 = Choice(poll=p1, choice='Because.')
|
|
c1.save()
|
|
c2 = Choice(poll=p1, choice='Why Not?')
|
|
c2.save()
|
|
|
|
# Exact query with value None returns nothing ("is NULL" in sql,
|
|
# but every 'id' field has a value).
|
|
self.assertQuerysetEqual(Choice.objects.filter(choice__exact=None), [])
|
|
|
|
# The same behavior for iexact query.
|
|
self.assertQuerysetEqual(Choice.objects.filter(choice__iexact=None), [])
|
|
|
|
# Excluding the previous result returns everything.
|
|
self.assertQuerysetEqual(
|
|
Choice.objects.exclude(choice=None).order_by('id'),
|
|
[
|
|
'<Choice: Choice: Because. in poll Q: Why? >',
|
|
'<Choice: Choice: Why Not? in poll Q: Why? >'
|
|
]
|
|
)
|
|
|
|
# Valid query, but fails because foo isn't a keyword
|
|
self.assertRaises(FieldError, Choice.objects.filter, foo__exact=None)
|
|
|
|
# Can't use None on anything other than __exact and __iexact
|
|
self.assertRaises(ValueError, Choice.objects.filter, id__gt=None)
|
|
|
|
# Related managers use __exact=None implicitly if the object hasn't been saved.
|
|
p2 = Poll(question="How?")
|
|
self.assertEqual(repr(p2.choice_set.all()), '[]')
|
|
|
|
def test_reverse_relations(self):
|
|
"""
|
|
Querying across reverse relations and then another relation should
|
|
insert outer joins correctly so as not to exclude results.
|
|
"""
|
|
obj = OuterA.objects.create()
|
|
self.assertQuerysetEqual(
|
|
OuterA.objects.filter(inner__third=None),
|
|
['<OuterA: OuterA object>']
|
|
)
|
|
self.assertQuerysetEqual(
|
|
OuterA.objects.filter(inner__third__data=None),
|
|
['<OuterA: OuterA object>']
|
|
)
|
|
|
|
Inner.objects.create(first=obj)
|
|
self.assertQuerysetEqual(
|
|
Inner.objects.filter(first__inner__third=None),
|
|
['<Inner: Inner object>']
|
|
)
|
|
|
|
# Ticket #13815: check if <reverse>_isnull=False does not produce
|
|
# faulty empty lists
|
|
OuterB.objects.create(data="reverse")
|
|
self.assertQuerysetEqual(
|
|
OuterB.objects.filter(inner__isnull=False),
|
|
[]
|
|
)
|
|
Inner.objects.create(first=obj)
|
|
self.assertQuerysetEqual(
|
|
OuterB.objects.exclude(inner__isnull=False),
|
|
['<OuterB: OuterB object>']
|
|
)
|