1 from __future__
import absolute_import
3 from datetime
import datetime
4 from operator
import attrgetter
6 from django
.db
.models
import Q
7 from django
.test
import TestCase
9 from .models
import Article
12 class OrLookupsTests(TestCase
):
15 self
.a1
= Article
.objects
.create(
16 headline
='Hello', pub_date
=datetime(2005, 11, 27)
18 self
.a2
= Article
.objects
.create(
19 headline
='Goodbye', pub_date
=datetime(2005, 11, 28)
21 self
.a3
= Article
.objects
.create(
22 headline
='Hello and goodbye', pub_date
=datetime(2005, 11, 29)
25 def test_filter_or(self
):
26 self
.assertQuerysetEqual(
27 Article
.objects
.filter(headline__startswith
='Hello') | Article
.objects
.filter(headline__startswith
='Goodbye'), [
32 attrgetter("headline")
35 self
.assertQuerysetEqual(
36 Article
.objects
.filter(headline__contains
='Hello') | Article
.objects
.filter(headline__contains
='bye'), [
41 attrgetter("headline")
44 self
.assertQuerysetEqual(
45 Article
.objects
.filter(headline__iexact
='Hello') | Article
.objects
.filter(headline__contains
='ood'), [
50 attrgetter("headline")
53 self
.assertQuerysetEqual(
54 Article
.objects
.filter(Q(headline__startswith
='Hello') |
Q(headline__startswith
='Goodbye')), [
59 attrgetter("headline")
63 def test_stages(self
):
64 # You can shorten this syntax with code like the following, which is
65 # especially useful if building the query in stages:
66 articles
= Article
.objects
.all()
67 self
.assertQuerysetEqual(
68 articles
.filter(headline__startswith
='Hello') & articles
.filter(headline__startswith
='Goodbye'),
71 self
.assertQuerysetEqual(
72 articles
.filter(headline__startswith
='Hello') & articles
.filter(headline__contains
='bye'), [
75 attrgetter("headline")
79 self
.assertQuerysetEqual(
80 Article
.objects
.filter(Q(pk
=self
.a1
) |
Q(pk
=self
.a2
)), [
84 attrgetter("headline")
87 self
.assertQuerysetEqual(
88 Article
.objects
.filter(Q(pk
=self
.a1
) |
Q(pk
=self
.a2
) |
Q(pk
=self
.a3
)), [
93 attrgetter("headline"),
97 self
.assertQuerysetEqual(
98 Article
.objects
.filter(pk__in
=[self
.a1
, self
.a2
, self
.a3
]), [
103 attrgetter("headline"),
106 self
.assertQuerysetEqual(
107 Article
.objects
.filter(pk__in
=(self
.a1
, self
.a2
, self
.a3
)), [
112 attrgetter("headline"),
115 self
.assertQuerysetEqual(
116 Article
.objects
.filter(pk__in
=[self
.a1
, self
.a2
, self
.a3
, 40000]), [
121 attrgetter("headline"),
124 def test_q_negated(self
):
125 # Q objects can be negated
126 self
.assertQuerysetEqual(
127 Article
.objects
.filter(Q(pk
=self
.a1
) | ~
Q(pk
=self
.a2
)), [
131 attrgetter("headline")
134 self
.assertQuerysetEqual(
135 Article
.objects
.filter(~
Q(pk
=self
.a1
) & ~
Q(pk
=self
.a2
)), [
138 attrgetter("headline"),
140 # This allows for more complex queries than filter() and exclude()
142 self
.assertQuerysetEqual(
143 Article
.objects
.filter(Q(pk
=self
.a1
) & (~
Q(pk
=self
.a2
) |
Q(pk
=self
.a3
))), [
146 attrgetter("headline"),
149 def test_complex_filter(self
):
150 # The 'complex_filter' method supports framework features such as
151 # 'limit_choices_to' which normally take a single dictionary of lookup
152 # arguments but need to support arbitrary queries via Q objects too.
153 self
.assertQuerysetEqual(
154 Article
.objects
.complex_filter({'pk': self
.a1
}), [
157 attrgetter("headline"),
160 self
.assertQuerysetEqual(
161 Article
.objects
.complex_filter(Q(pk
=self
.a1
) |
Q(pk
=self
.a2
)), [
165 attrgetter("headline"),
168 def test_empty_in(self
):
169 # Passing "in" an empty list returns no results ...
170 self
.assertQuerysetEqual(
171 Article
.objects
.filter(pk__in
=[]),
174 # ... but can return results if we OR it with another query.
175 self
.assertQuerysetEqual(
176 Article
.objects
.filter(Q(pk__in
=[]) |
Q(headline__icontains
='goodbye')), [
180 attrgetter("headline"),
183 def test_q_and(self
):
184 # Q arg objects are ANDed
185 self
.assertQuerysetEqual(
186 Article
.objects
.filter(Q(headline__startswith
='Hello'), Q(headline__contains
='bye')), [
189 attrgetter("headline")
191 # Q arg AND order is irrelevant
192 self
.assertQuerysetEqual(
193 Article
.objects
.filter(Q(headline__contains
='bye'), headline__startswith
='Hello'), [
196 attrgetter("headline"),
199 self
.assertQuerysetEqual(
200 Article
.objects
.filter(Q(headline__startswith
='Hello') & Q(headline__startswith
='Goodbye')),
204 def test_q_exclude(self
):
205 self
.assertQuerysetEqual(
206 Article
.objects
.exclude(Q(headline__startswith
='Hello')), [
209 attrgetter("headline")
212 def test_other_arg_queries(self
):
213 # Try some arg queries with operations other than filter.
215 Article
.objects
.get(Q(headline__startswith
='Hello'), Q(headline__contains
='bye')).headline
,
220 Article
.objects
.filter(Q(headline__startswith
='Hello') |
Q(headline__contains
='bye')).count(),
224 self
.assertQuerysetEqual(
225 Article
.objects
.filter(Q(headline__startswith
='Hello'), Q(headline__contains
='bye')).values(), [
226 {"headline": "Hello and goodbye", "id": self
.a3
, "pub_date": datetime(2005, 11, 29)},
232 Article
.objects
.filter(Q(headline__startswith
='Hello')).in_bulk([self
.a1
, self
.a2
]),
233 {self
.a1
: Article
.objects
.get(pk
=self
.a1
)}