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)}