parts/django/tests/modeltests/or_lookups/tests.py
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 from datetime import datetime
       
     2 from operator import attrgetter
       
     3 
       
     4 from django.db.models import Q
       
     5 from django.test import TestCase
       
     6 
       
     7 from models import Article
       
     8 
       
     9 
       
    10 class OrLookupsTests(TestCase):
       
    11 
       
    12     def setUp(self):
       
    13         self.a1 = Article.objects.create(
       
    14             headline='Hello', pub_date=datetime(2005, 11, 27)
       
    15         ).pk
       
    16         self.a2 = Article.objects.create(
       
    17             headline='Goodbye', pub_date=datetime(2005, 11, 28)
       
    18         ).pk
       
    19         self.a3 = Article.objects.create(
       
    20             headline='Hello and goodbye', pub_date=datetime(2005, 11, 29)
       
    21         ).pk
       
    22 
       
    23     def test_filter_or(self):
       
    24         self.assertQuerysetEqual(
       
    25             Article.objects.filter(headline__startswith='Hello') |  Article.objects.filter(headline__startswith='Goodbye'), [
       
    26                 'Hello',
       
    27                 'Goodbye',
       
    28                 'Hello and goodbye'
       
    29             ],
       
    30             attrgetter("headline")
       
    31         )
       
    32 
       
    33         self.assertQuerysetEqual(
       
    34             Article.objects.filter(headline__contains='Hello') | Article.objects.filter(headline__contains='bye'), [
       
    35                 'Hello',
       
    36                 'Goodbye',
       
    37                 'Hello and goodbye'
       
    38             ],
       
    39             attrgetter("headline")
       
    40         )
       
    41 
       
    42         self.assertQuerysetEqual(
       
    43             Article.objects.filter(headline__iexact='Hello') | Article.objects.filter(headline__contains='ood'), [
       
    44                 'Hello',
       
    45                 'Goodbye',
       
    46                 'Hello and goodbye'
       
    47             ],
       
    48             attrgetter("headline")
       
    49         )
       
    50 
       
    51         self.assertQuerysetEqual(
       
    52             Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__startswith='Goodbye')), [
       
    53                 'Hello',
       
    54                 'Goodbye',
       
    55                 'Hello and goodbye'
       
    56             ],
       
    57             attrgetter("headline")
       
    58         )
       
    59 
       
    60 
       
    61     def test_stages(self):
       
    62         # You can shorten this syntax with code like the following,  which is
       
    63         # especially useful if building the query in stages:
       
    64         articles = Article.objects.all()
       
    65         self.assertQuerysetEqual(
       
    66             articles.filter(headline__startswith='Hello') & articles.filter(headline__startswith='Goodbye'),
       
    67             []
       
    68         )
       
    69         self.assertQuerysetEqual(
       
    70             articles.filter(headline__startswith='Hello') & articles.filter(headline__contains='bye'), [
       
    71                 'Hello and goodbye'
       
    72             ],
       
    73             attrgetter("headline")
       
    74         )
       
    75 
       
    76     def test_pk_q(self):
       
    77         self.assertQuerysetEqual(
       
    78             Article.objects.filter(Q(pk=self.a1) | Q(pk=self.a2)), [
       
    79                 'Hello',
       
    80                 'Goodbye'
       
    81             ],
       
    82             attrgetter("headline")
       
    83         )
       
    84 
       
    85         self.assertQuerysetEqual(
       
    86             Article.objects.filter(Q(pk=self.a1) | Q(pk=self.a2) | Q(pk=self.a3)), [
       
    87                 'Hello',
       
    88                 'Goodbye',
       
    89                 'Hello and goodbye'
       
    90             ],
       
    91             attrgetter("headline"),
       
    92         )
       
    93 
       
    94     def test_pk_in(self):
       
    95         self.assertQuerysetEqual(
       
    96             Article.objects.filter(pk__in=[self.a1, self.a2, self.a3]), [
       
    97                 'Hello',
       
    98                 'Goodbye',
       
    99                 'Hello and goodbye'
       
   100             ],
       
   101             attrgetter("headline"),
       
   102         )
       
   103 
       
   104         self.assertQuerysetEqual(
       
   105             Article.objects.filter(pk__in=(self.a1, self.a2, self.a3)), [
       
   106                 'Hello',
       
   107                 'Goodbye',
       
   108                 'Hello and goodbye'
       
   109             ],
       
   110             attrgetter("headline"),
       
   111         )
       
   112 
       
   113         self.assertQuerysetEqual(
       
   114             Article.objects.filter(pk__in=[self.a1, self.a2, self.a3, 40000]), [
       
   115                 'Hello',
       
   116                 'Goodbye',
       
   117                 'Hello and goodbye'
       
   118             ],
       
   119             attrgetter("headline"),
       
   120         )
       
   121 
       
   122     def test_q_negated(self):
       
   123         # Q objects can be negated
       
   124         self.assertQuerysetEqual(
       
   125             Article.objects.filter(Q(pk=self.a1) | ~Q(pk=self.a2)), [
       
   126                 'Hello',
       
   127                 'Hello and goodbye'
       
   128             ],
       
   129             attrgetter("headline")
       
   130         )
       
   131 
       
   132         self.assertQuerysetEqual(
       
   133             Article.objects.filter(~Q(pk=self.a1) & ~Q(pk=self.a2)), [
       
   134                 'Hello and goodbye'
       
   135             ],
       
   136             attrgetter("headline"),
       
   137         )
       
   138         # This allows for more complex queries than filter() and exclude()
       
   139         # alone would allow
       
   140         self.assertQuerysetEqual(
       
   141             Article.objects.filter(Q(pk=self.a1) & (~Q(pk=self.a2) | Q(pk=self.a3))), [
       
   142                 'Hello'
       
   143             ],
       
   144             attrgetter("headline"),
       
   145         )
       
   146 
       
   147     def test_complex_filter(self):
       
   148         # The 'complex_filter' method supports framework features such as
       
   149         # 'limit_choices_to' which normally take a single dictionary of lookup
       
   150         # arguments but need to support arbitrary queries via Q objects too.
       
   151         self.assertQuerysetEqual(
       
   152             Article.objects.complex_filter({'pk': self.a1}), [
       
   153                 'Hello'
       
   154             ],
       
   155             attrgetter("headline"),
       
   156         )
       
   157 
       
   158         self.assertQuerysetEqual(
       
   159             Article.objects.complex_filter(Q(pk=self.a1) | Q(pk=self.a2)), [
       
   160                 'Hello',
       
   161                 'Goodbye'
       
   162             ],
       
   163             attrgetter("headline"),
       
   164         )
       
   165 
       
   166     def test_empty_in(self):
       
   167         # Passing "in" an empty list returns no results ...
       
   168         self.assertQuerysetEqual(
       
   169             Article.objects.filter(pk__in=[]),
       
   170             []
       
   171         )
       
   172         # ... but can return results if we OR it with another query.
       
   173         self.assertQuerysetEqual(
       
   174             Article.objects.filter(Q(pk__in=[]) | Q(headline__icontains='goodbye')), [
       
   175                 'Goodbye',
       
   176                 'Hello and goodbye'
       
   177             ],
       
   178             attrgetter("headline"),
       
   179         )
       
   180 
       
   181     def test_q_and(self):
       
   182         # Q arg objects are ANDed
       
   183         self.assertQuerysetEqual(
       
   184             Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye')), [
       
   185                 'Hello and goodbye'
       
   186             ],
       
   187             attrgetter("headline")
       
   188         )
       
   189         # Q arg AND order is irrelevant
       
   190         self.assertQuerysetEqual(
       
   191             Article.objects.filter(Q(headline__contains='bye'), headline__startswith='Hello'), [
       
   192                 'Hello and goodbye'
       
   193             ],
       
   194             attrgetter("headline"),
       
   195         )
       
   196 
       
   197         self.assertQuerysetEqual(
       
   198             Article.objects.filter(Q(headline__startswith='Hello') & Q(headline__startswith='Goodbye')),
       
   199             []
       
   200         )
       
   201 
       
   202     def test_q_exclude(self):
       
   203         self.assertQuerysetEqual(
       
   204             Article.objects.exclude(Q(headline__startswith='Hello')), [
       
   205                 'Goodbye'
       
   206             ],
       
   207             attrgetter("headline")
       
   208         )
       
   209 
       
   210     def test_other_arg_queries(self):
       
   211         # Try some arg queries with operations other than filter.
       
   212         self.assertEqual(
       
   213             Article.objects.get(Q(headline__startswith='Hello'), Q(headline__contains='bye')).headline,
       
   214             'Hello and goodbye'
       
   215         )
       
   216 
       
   217         self.assertEqual(
       
   218             Article.objects.filter(Q(headline__startswith='Hello') | Q(headline__contains='bye')).count(),
       
   219             3
       
   220         )
       
   221 
       
   222         self.assertQuerysetEqual(
       
   223             Article.objects.filter(Q(headline__startswith='Hello'), Q(headline__contains='bye')).values(), [
       
   224                 {"headline": "Hello and goodbye", "id": self.a3, "pub_date": datetime(2005, 11, 29)},
       
   225             ],
       
   226             lambda o: o,
       
   227         )
       
   228 
       
   229         self.assertEqual(
       
   230             Article.objects.filter(Q(headline__startswith='Hello')).in_bulk([self.a1, self.a2]),
       
   231             {self.a1: Article.objects.get(pk=self.a1)}
       
   232         )