Esempio n. 1
0
 def test_order_by_on_list_field(self):
     # Test order_by() on list fields where some values are empty
     test_items = []
     for i in range(4):
         item = self.get_test_item()
         item.subject = self.categories[
             0]  # Make sure we have something unique to filter on
         if i % 2 == 0:
             item.categories = ['Cat %s' % i]
         else:
             item.categories = []
         test_items.append(item)
     self.test_folder.bulk_create(items=test_items)
     qs = QuerySet(folder_collection=FolderCollection(
         account=self.account, folders=[self.test_folder])).filter(
             subject=self.categories[0])
     self.assertEqual(
         list(
             qs.order_by('categories').values_list('categories',
                                                   flat=True)),
         [None, None, ['Cat 0'], ['Cat 2']])
     self.assertEqual(
         list(
             qs.order_by('-categories').values_list('categories',
                                                    flat=True)),
         [['Cat 2'], ['Cat 0'], None, None])
Esempio n. 2
0
 def test_magic(self):
     self.assertEqual(
         str(
             QuerySet(folder_collection=FolderCollection(
                 account=None, folders=[Inbox(root='XXX', name='FooBox')
                                        ]))),
         'QuerySet(q=Q(), folders=[Inbox (FooBox)])')
Esempio n. 3
0
 def test_magic(self):
     self.assertEqual(
         str(
             QuerySet(folder_collection=FolderCollection(
                 account=None, folders=[Inbox(root="XXX", name="FooBox")
                                        ]))),
         "QuerySet(q=Q(), folders=[Inbox (FooBox)])",
     )
Esempio n. 4
0
    def test_queryset_copy(self):
        qs = QuerySet(folder_collection=FolderCollection(
            account=None, folders=[Inbox(root='XXX')]))
        qs.q = Q()
        qs.only_fields = ('a', 'b')
        qs.order_fields = ('c', 'd')
        qs.return_format = QuerySet.NONE

        # Initially, immutable items have the same id()
        new_qs = qs._copy_self()
        self.assertNotEqual(id(qs), id(new_qs))
        self.assertEqual(id(qs.folder_collection),
                         id(new_qs.folder_collection))
        self.assertEqual(id(qs._cache), id(new_qs._cache))
        self.assertEqual(qs._cache, new_qs._cache)
        self.assertNotEqual(id(qs.q), id(new_qs.q))
        self.assertEqual(qs.q, new_qs.q)
        self.assertEqual(id(qs.only_fields), id(new_qs.only_fields))
        self.assertEqual(qs.only_fields, new_qs.only_fields)
        self.assertEqual(id(qs.order_fields), id(new_qs.order_fields))
        self.assertEqual(qs.order_fields, new_qs.order_fields)
        self.assertEqual(id(qs.return_format), id(new_qs.return_format))
        self.assertEqual(qs.return_format, new_qs.return_format)

        # Set the same values, forcing a new id()
        new_qs.q = Q()
        new_qs.only_fields = ('a', 'b')
        new_qs.order_fields = ('c', 'd')
        new_qs.return_format = QuerySet.NONE

        self.assertNotEqual(id(qs), id(new_qs))
        self.assertEqual(id(qs.folder_collection),
                         id(new_qs.folder_collection))
        self.assertEqual(id(qs._cache), id(new_qs._cache))
        self.assertEqual(qs._cache, new_qs._cache)
        self.assertNotEqual(id(qs.q), id(new_qs.q))
        self.assertEqual(qs.q, new_qs.q)
        self.assertEqual(qs.only_fields, new_qs.only_fields)
        self.assertEqual(qs.order_fields, new_qs.order_fields)
        self.assertEqual(qs.return_format, new_qs.return_format)

        # Set the new values, forcing a new id()
        new_qs.q = Q(foo=5)
        new_qs.only_fields = ('c', 'd')
        new_qs.order_fields = ('e', 'f')
        new_qs.return_format = QuerySet.VALUES

        self.assertNotEqual(id(qs), id(new_qs))
        self.assertEqual(id(qs.folder_collection),
                         id(new_qs.folder_collection))
        self.assertEqual(id(qs._cache), id(new_qs._cache))
        self.assertEqual(qs._cache, new_qs._cache)
        self.assertNotEqual(id(qs.q), id(new_qs.q))
        self.assertNotEqual(qs.q, new_qs.q)
        self.assertNotEqual(id(qs.only_fields), id(new_qs.only_fields))
        self.assertNotEqual(qs.only_fields, new_qs.only_fields)
        self.assertNotEqual(id(qs.order_fields), id(new_qs.order_fields))
        self.assertNotEqual(qs.order_fields, new_qs.order_fields)
        self.assertNotEqual(id(qs.return_format), id(new_qs.return_format))
        self.assertNotEqual(qs.return_format, new_qs.return_format)
Esempio n. 5
0
 def test_order_by_with_empty_values(self):
     # Test order_by() when some values are empty
     test_items = []
     for i in range(4):
         item = self.get_test_item()
         if i % 2 == 0:
             item.subject = 'Subj %s' % i
         else:
             item.subject = None
         test_items.append(item)
     self.test_folder.bulk_create(items=test_items)
     qs = QuerySet(folder_collection=FolderCollection(
         account=self.account, folders=[self.test_folder])).filter(
             categories__contains=self.categories)
     self.assertEqual(
         list(qs.order_by('subject').values_list('subject', flat=True)),
         [None, None, 'Subj 0', 'Subj 2'])
     self.assertEqual(
         list(qs.order_by('-subject').values_list('subject', flat=True)),
         ['Subj 2', 'Subj 0', None, None])
Esempio n. 6
0
    def test_order_by_on_indexed_field(self):
        # Test order_by() on IndexedField (simple and multi-subfield). Only Contact items have these
        test_items = []
        label = self.random_val(EmailAddress.get_field_by_fieldname('label'))
        for i in range(4):
            item = self.get_test_item()
            item.email_addresses = [
                EmailAddress(email='*****@*****.**' % i, label=label)
            ]
            test_items.append(item)
        self.test_folder.bulk_create(items=test_items)
        qs = QuerySet(folder_collection=FolderCollection(
            account=self.account, folders=[self.test_folder])).filter(
                categories__contains=self.categories)
        self.assertEqual([
            i[0].email
            for i in qs.order_by('email_addresses__%s' % label).values_list(
                'email_addresses', flat=True)
        ], ['*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**'])
        self.assertEqual([
            i[0].email
            for i in qs.order_by('-email_addresses__%s' % label).values_list(
                'email_addresses', flat=True)
        ], ['*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**'])
        self.bulk_delete(qs)

        test_items = []
        label = self.random_val(
            PhysicalAddress.get_field_by_fieldname('label'))
        for i in range(4):
            item = self.get_test_item()
            item.physical_addresses = [
                PhysicalAddress(street='Elm St %s' % i, label=label)
            ]
            test_items.append(item)
        self.test_folder.bulk_create(items=test_items)
        qs = QuerySet(folder_collection=FolderCollection(
            account=self.account, folders=[self.test_folder])).filter(
                categories__contains=self.categories)
        self.assertEqual([
            i[0].street
            for i in qs.order_by('physical_addresses__%s__street' % label).
            values_list('physical_addresses', flat=True)
        ], ['Elm St 0', 'Elm St 1', 'Elm St 2', 'Elm St 3'])
        self.assertEqual([
            i[0].street
            for i in qs.order_by('-physical_addresses__%s__street' % label).
            values_list('physical_addresses', flat=True)
        ], ['Elm St 3', 'Elm St 2', 'Elm St 1', 'Elm St 0'])
        self.bulk_delete(qs)
Esempio n. 7
0
 def test_cached_queryset_corner_cases(self):
     test_items = []
     for i in range(4):
         item = self.get_test_item()
         item.subject = 'Item %s' % i
         item.save()
         test_items.append(item)
     qs = QuerySet(
         folder_collection=FolderCollection(account=self.account, folders=[self.test_folder])
     ).filter(categories__contains=self.categories).order_by('subject')
     with self.assertRaises(MultipleObjectsReturned):
         qs.get()  # Get with a full cache
     self.assertEqual(qs[2].subject, 'Item 2')  # Index with a full cache
     self.assertEqual(qs[-2].subject, 'Item 2')  # Negative index with a full cache
     qs.delete()  # Delete with a full cache
     self.assertEqual(qs.count(), 0)  # QuerySet is empty after delete
     self.assertEqual(list(qs.none()), [])
Esempio n. 8
0
    def test_order_by(self):
        # Test order_by() on normal field
        test_items = []
        for i in range(4):
            item = self.get_test_item()
            item.subject = 'Subj %s' % i
            test_items.append(item)
        self.test_folder.bulk_create(items=test_items)
        qs = QuerySet(folder_collection=FolderCollection(
            account=self.account, folders=[self.test_folder])).filter(
                categories__contains=self.categories)
        self.assertEqual([
            i for i in qs.order_by('subject').values_list('subject', flat=True)
        ], ['Subj 0', 'Subj 1', 'Subj 2', 'Subj 3'])
        self.assertEqual([
            i
            for i in qs.order_by('-subject').values_list('subject', flat=True)
        ], ['Subj 3', 'Subj 2', 'Subj 1', 'Subj 0'])
        self.bulk_delete(qs)

        try:
            self.ITEM_CLASS.register('extern_id', ExternId)
            # Test order_by() on ExtendedProperty
            test_items = []
            for i in range(4):
                item = self.get_test_item()
                item.extern_id = 'ID %s' % i
                test_items.append(item)
            self.test_folder.bulk_create(items=test_items)
            qs = QuerySet(folder_collection=FolderCollection(
                account=self.account, folders=[self.test_folder])).filter(
                    categories__contains=self.categories)
            self.assertEqual([
                i for i in qs.order_by('extern_id').values_list('extern_id',
                                                                flat=True)
            ], ['ID 0', 'ID 1', 'ID 2', 'ID 3'])
            self.assertEqual([
                i for i in qs.order_by('-extern_id').values_list('extern_id',
                                                                 flat=True)
            ], ['ID 3', 'ID 2', 'ID 1', 'ID 0'])
        finally:
            self.ITEM_CLASS.deregister('extern_id')
        self.bulk_delete(qs)

        # Test sorting on multiple fields
        try:
            self.ITEM_CLASS.register('extern_id', ExternId)
            test_items = []
            for i in range(2):
                for j in range(2):
                    item = self.get_test_item()
                    item.subject = 'Subj %s' % i
                    item.extern_id = 'ID %s' % j
                    test_items.append(item)
            self.test_folder.bulk_create(items=test_items)
            qs = QuerySet(folder_collection=FolderCollection(
                account=self.account, folders=[self.test_folder])).filter(
                    categories__contains=self.categories)
            self.assertEqual([
                i for i in qs.order_by('subject', 'extern_id').values(
                    'subject', 'extern_id')
            ], [{
                'subject': 'Subj 0',
                'extern_id': 'ID 0'
            }, {
                'subject': 'Subj 0',
                'extern_id': 'ID 1'
            }, {
                'subject': 'Subj 1',
                'extern_id': 'ID 0'
            }, {
                'subject': 'Subj 1',
                'extern_id': 'ID 1'
            }])
            self.assertEqual([
                i for i in qs.order_by('-subject', 'extern_id').values(
                    'subject', 'extern_id')
            ], [{
                'subject': 'Subj 1',
                'extern_id': 'ID 0'
            }, {
                'subject': 'Subj 1',
                'extern_id': 'ID 1'
            }, {
                'subject': 'Subj 0',
                'extern_id': 'ID 0'
            }, {
                'subject': 'Subj 0',
                'extern_id': 'ID 1'
            }])
            self.assertEqual([
                i for i in qs.order_by('subject', '-extern_id').values(
                    'subject', 'extern_id')
            ], [{
                'subject': 'Subj 0',
                'extern_id': 'ID 1'
            }, {
                'subject': 'Subj 0',
                'extern_id': 'ID 0'
            }, {
                'subject': 'Subj 1',
                'extern_id': 'ID 1'
            }, {
                'subject': 'Subj 1',
                'extern_id': 'ID 0'
            }])
            self.assertEqual([
                i for i in qs.order_by('-subject', '-extern_id').values(
                    'subject', 'extern_id')
            ], [{
                'subject': 'Subj 1',
                'extern_id': 'ID 1'
            }, {
                'subject': 'Subj 1',
                'extern_id': 'ID 0'
            }, {
                'subject': 'Subj 0',
                'extern_id': 'ID 1'
            }, {
                'subject': 'Subj 0',
                'extern_id': 'ID 0'
            }])
        finally:
            self.ITEM_CLASS.deregister('extern_id')
Esempio n. 9
0
 def test_queryset_failure(self):
     qs = QuerySet(folder_collection=FolderCollection(
         account=self.account, folders=[self.test_folder])).filter(
             categories__contains=self.categories)
     with self.assertRaises(ValueError):
         qs.order_by('XXX')
     with self.assertRaises(ValueError):
         qs.values('XXX')
     with self.assertRaises(ValueError):
         qs.values_list('XXX')
     with self.assertRaises(ValueError):
         qs.only('XXX')
     with self.assertRaises(ValueError):
         qs.reverse(
         )  # We can't reverse when we haven't defined an order yet
Esempio n. 10
0
    def test_querysets(self):
        test_items = []
        for i in range(4):
            item = self.get_test_item()
            item.subject = 'Item %s' % i
            item.save()
            test_items.append(item)
        qs = QuerySet(folder_collection=FolderCollection(
            account=self.account, folders=[self.test_folder])).filter(
                categories__contains=self.categories)
        test_cat = self.categories[0]
        self.assertEqual(
            set((i.subject, i.categories[0]) for i in qs),
            {('Item 0', test_cat), ('Item 1', test_cat), ('Item 2', test_cat),
             ('Item 3', test_cat)})
        self.assertEqual([(i.subject, i.categories[0]) for i in qs.none()], [])
        self.assertEqual([(i.subject, i.categories[0])
                          for i in qs.filter(subject__startswith='Item 2')],
                         [('Item 2', test_cat)])
        self.assertEqual(
            set((i.subject, i.categories[0])
                for i in qs.exclude(subject__startswith='Item 2')),
            {('Item 0', test_cat), ('Item 1', test_cat), ('Item 3', test_cat)})
        self.assertEqual(
            set((i.subject, i.categories) for i in qs.only('subject')),
            {('Item 0', None), ('Item 1', None), ('Item 2', None),
             ('Item 3', None)})
        self.assertEqual([(i.subject, i.categories[0])
                          for i in qs.order_by('subject')],
                         [('Item 0', test_cat), ('Item 1', test_cat),
                          ('Item 2', test_cat), ('Item 3', test_cat)])
        self.assertEqual(  # Test '-some_field' syntax for reverse sorting
            [(i.subject, i.categories[0]) for i in qs.order_by('-subject')],
            [('Item 3', test_cat), ('Item 2', test_cat), ('Item 1', test_cat),
             ('Item 0', test_cat)])
        self.assertEqual(  # Test ordering on a field that we don't need to fetch
            [(i.subject, i.categories[0])
             for i in qs.order_by('-subject').only('categories')],
            [(None, test_cat), (None, test_cat), (None, test_cat),
             (None, test_cat)])
        self.assertEqual([(i.subject, i.categories[0])
                          for i in qs.order_by('subject').reverse()],
                         [('Item 3', test_cat), ('Item 2', test_cat),
                          ('Item 1', test_cat), ('Item 0', test_cat)])
        with self.assertRaises(ValueError):
            list(qs.values([]))
        self.assertEqual([i for i in qs.order_by('subject').values('subject')],
                         [{
                             'subject': 'Item 0'
                         }, {
                             'subject': 'Item 1'
                         }, {
                             'subject': 'Item 2'
                         }, {
                             'subject': 'Item 3'
                         }])

        # Test .values() in combinations of 'id' and 'changekey', which are handled specially
        self.assertEqual(list(qs.order_by('subject').values('id')), [{
            'id': i.id
        } for i in test_items])
        self.assertEqual(list(qs.order_by('subject').values('changekey')),
                         [{
                             'changekey': i.changekey
                         } for i in test_items])
        self.assertEqual(
            list(qs.order_by('subject').values('id', 'changekey')),
            [{k: getattr(i, k)
              for k in ('id', 'changekey')} for i in test_items])

        self.assertEqual(set(i for i in qs.values_list('subject')),
                         {('Item 0', ), ('Item 1', ), ('Item 2', ),
                          ('Item 3', )})

        # Test .values_list() in combinations of 'id' and 'changekey', which are handled specially
        self.assertEqual(list(qs.order_by('subject').values_list('id')),
                         [(i.id, ) for i in test_items])
        self.assertEqual(list(qs.order_by('subject').values_list('changekey')),
                         [(i.changekey, ) for i in test_items])
        self.assertEqual(
            list(qs.order_by('subject').values_list('id', 'changekey')),
            [(i.id, i.changekey) for i in test_items])

        self.assertEqual(set(i.subject for i in qs.only('subject')),
                         {'Item 0', 'Item 1', 'Item 2', 'Item 3'})

        # Test .only() in combinations of 'id' and 'changekey', which are handled specially
        self.assertEqual(
            list((i.id, ) for i in qs.order_by('subject').only('id')),
            [(i.id, ) for i in test_items])
        self.assertEqual(
            list((i.changekey, )
                 for i in qs.order_by('subject').only('changekey')),
            [(i.changekey, ) for i in test_items])
        self.assertEqual(
            list((i.id, i.changekey)
                 for i in qs.order_by('subject').only('id', 'changekey')),
            [(i.id, i.changekey) for i in test_items])

        with self.assertRaises(ValueError):
            list(qs.values_list('id', 'changekey', flat=True))
        with self.assertRaises(AttributeError):
            list(qs.values_list('id', xxx=True))
        self.assertEqual(
            list(qs.order_by('subject').values_list('id', flat=True)),
            [i.id for i in test_items])
        self.assertEqual(
            list(qs.order_by('subject').values_list('changekey', flat=True)),
            [i.changekey for i in test_items])
        self.assertEqual(set(i for i in qs.values_list('subject', flat=True)),
                         {'Item 0', 'Item 1', 'Item 2', 'Item 3'})
        self.assertEqual(
            qs.values_list('subject', flat=True).get(subject='Item 2'),
            'Item 2')
        self.assertEqual(
            set((i.subject, i.categories[0])
                for i in qs.exclude(subject__startswith='Item 2')),
            {('Item 0', test_cat), ('Item 1', test_cat), ('Item 3', test_cat)})
        # Test that we can sort on a field that we don't want
        self.assertEqual([
            i.categories[0] for i in qs.only('categories').order_by('subject')
        ], [test_cat, test_cat, test_cat, test_cat])
        # Test iterator
        self.assertEqual(
            set((i.subject, i.categories[0]) for i in qs.iterator()),
            {('Item 0', test_cat), ('Item 1', test_cat), ('Item 2', test_cat),
             ('Item 3', test_cat)})
        # Test that iterator() preserves the result format
        self.assertEqual(
            set((i[0], i[1][0])
                for i in qs.values_list('subject', 'categories').iterator()),
            {('Item 0', test_cat), ('Item 1', test_cat), ('Item 2', test_cat),
             ('Item 3', test_cat)})
        self.assertEqual(qs.get(subject='Item 3').subject, 'Item 3')
        with self.assertRaises(DoesNotExist):
            qs.get(subject='Item XXX')
        with self.assertRaises(MultipleObjectsReturned):
            qs.get(subject__startswith='Item')
        # len() and count()
        self.assertEqual(qs.count(), 4)
        # Indexing and slicing
        self.assertTrue(isinstance(qs[0], self.ITEM_CLASS))
        self.assertEqual(len(list(qs[1:3])), 2)
        self.assertEqual(qs.count(), 4)
        with self.assertRaises(IndexError):
            print(qs[99999])
        # Exists
        self.assertEqual(qs.exists(), True)
        self.assertEqual(qs.filter(subject='Test XXX').exists(), False)
        self.assertEqual(
            qs.filter(subject__startswith='Item').delete(),
            [True, True, True, True])
Esempio n. 11
0
 def test_order_by_failure(self):
     # Test error handling on indexed properties with labels and subfields
     qs = QuerySet(
         folder_collection=FolderCollection(account=self.account, folders=[self.test_folder])
     ).filter(categories__contains=self.categories)
     with self.assertRaises(ValueError):
         qs.order_by('email_addresses')  # Must have label
     with self.assertRaises(ValueError):
         qs.order_by('email_addresses__FOO')  # Must have a valid label
     with self.assertRaises(ValueError):
         qs.order_by('email_addresses__EmailAddress1__FOO')  # Must not have a subfield
     with self.assertRaises(ValueError):
         qs.order_by('physical_addresses__Business')  # Must have a subfield
     with self.assertRaises(ValueError):
         qs.order_by('physical_addresses__Business__FOO')  # Must have a valid subfield
Esempio n. 12
0
    def test_querysets(self):
        test_items = []
        for i in range(4):
            item = self.get_test_item()
            item.subject = f"Item {i}"
            item.save()
            test_items.append(item)
        qs = QuerySet(folder_collection=FolderCollection(
            account=self.account, folders=[self.test_folder])).filter(
                categories__contains=self.categories)
        test_cat = self.categories[0]
        self.assertEqual(
            {(i.subject, i.categories[0])
             for i in qs},
            {("Item 0", test_cat), ("Item 1", test_cat), ("Item 2", test_cat),
             ("Item 3", test_cat)},
        )
        self.assertEqual([(i.subject, i.categories[0]) for i in qs.none()], [])
        self.assertEqual([(i.subject, i.categories[0])
                          for i in qs.filter(subject__startswith="Item 2")],
                         [("Item 2", test_cat)])
        self.assertEqual(
            {(i.subject, i.categories[0])
             for i in qs.exclude(subject__startswith="Item 2")},
            {("Item 0", test_cat), ("Item 1", test_cat), ("Item 3", test_cat)},
        )
        self.assertEqual(
            {(i.subject, i.categories)
             for i in qs.only("subject")},
            {("Item 0", None), ("Item 1", None), ("Item 2", None),
             ("Item 3", None)},
        )
        self.assertEqual(
            [(i.subject, i.categories[0]) for i in qs.order_by("subject")],
            [("Item 0", test_cat), ("Item 1", test_cat), ("Item 2", test_cat),
             ("Item 3", test_cat)],
        )
        self.assertEqual(  # Test '-some_field' syntax for reverse sorting
            [(i.subject, i.categories[0]) for i in qs.order_by("-subject")],
            [("Item 3", test_cat), ("Item 2", test_cat), ("Item 1", test_cat),
             ("Item 0", test_cat)],
        )
        self.assertEqual(  # Test ordering on a field that we don't need to fetch
            [(i.subject, i.categories[0])
             for i in qs.order_by("-subject").only("categories")],
            [(None, test_cat), (None, test_cat), (None, test_cat),
             (None, test_cat)],
        )
        self.assertEqual(
            [(i.subject, i.categories[0])
             for i in qs.order_by("subject").reverse()],
            [("Item 3", test_cat), ("Item 2", test_cat), ("Item 1", test_cat),
             ("Item 0", test_cat)],
        )
        with self.assertRaises(TypeError):
            list(qs.values([]))
        self.assertEqual(
            list(qs.order_by("subject").values("subject")),
            [{
                "subject": "Item 0"
            }, {
                "subject": "Item 1"
            }, {
                "subject": "Item 2"
            }, {
                "subject": "Item 3"
            }],
        )

        # Test .values() in combinations of 'id' and 'changekey', which are handled specially
        self.assertEqual(list(qs.order_by("subject").values("id")), [{
            "id": i.id
        } for i in test_items])
        self.assertEqual(list(qs.order_by("subject").values("changekey")),
                         [{
                             "changekey": i.changekey
                         } for i in test_items])
        self.assertEqual(
            list(qs.order_by("subject").values("id", "changekey")),
            [{k: getattr(i, k)
              for k in ("id", "changekey")} for i in test_items],
        )

        self.assertEqual(set(qs.values_list("subject")), {("Item 0", ),
                                                          ("Item 1", ),
                                                          ("Item 2", ),
                                                          ("Item 3", )})

        # Test .values_list() in combinations of 'id' and 'changekey', which are handled specially
        self.assertEqual(list(qs.order_by("subject").values_list("id")),
                         [(i.id, ) for i in test_items])
        self.assertEqual(list(qs.order_by("subject").values_list("changekey")),
                         [(i.changekey, ) for i in test_items])
        self.assertEqual(
            list(qs.order_by("subject").values_list("id", "changekey")),
            [(i.id, i.changekey) for i in test_items])

        self.assertEqual({i.subject
                          for i in qs.only("subject")},
                         {"Item 0", "Item 1", "Item 2", "Item 3"})

        # Test .only() in combinations of 'id' and 'changekey', which are handled specially
        self.assertEqual([(i.id, ) for i in qs.order_by("subject").only("id")],
                         [(i.id, ) for i in test_items])
        self.assertEqual([(i.changekey, )
                          for i in qs.order_by("subject").only("changekey")],
                         [(i.changekey, ) for i in test_items])
        self.assertEqual(
            [(i.id, i.changekey)
             for i in qs.order_by("subject").only("id", "changekey")],
            [(i.id, i.changekey) for i in test_items],
        )

        with self.assertRaises(ValueError):
            list(qs.values_list("id", "changekey", flat=True))
        with self.assertRaises(AttributeError):
            list(qs.values_list("id", xxx=True))
        self.assertEqual(
            list(qs.order_by("subject").values_list("id", flat=True)),
            [i.id for i in test_items])
        self.assertEqual(
            list(qs.order_by("subject").values_list("changekey", flat=True)),
            [i.changekey for i in test_items])
        self.assertEqual(set(qs.values_list("subject", flat=True)),
                         {"Item 0", "Item 1", "Item 2", "Item 3"})
        self.assertEqual(
            qs.values_list("subject", flat=True).get(subject="Item 2"),
            "Item 2")
        self.assertEqual(
            {(i.subject, i.categories[0])
             for i in qs.exclude(subject__startswith="Item 2")},
            {("Item 0", test_cat), ("Item 1", test_cat), ("Item 3", test_cat)},
        )
        # Test that we can sort on a field that we don't want
        self.assertEqual(
            [
                i.categories[0]
                for i in qs.only("categories").order_by("subject")
            ],
            [test_cat, test_cat, test_cat, test_cat],
        )
        self.assertEqual(qs.get(subject="Item 3").subject, "Item 3")
        with self.assertRaises(DoesNotExist):
            qs.get(subject="Item XXX")
        with self.assertRaises(MultipleObjectsReturned):
            qs.get(subject__startswith="Item")
        # len() and count()
        self.assertEqual(qs.count(), 4)
        # Indexing and slicing
        self.assertIsInstance(qs[0], self.ITEM_CLASS)
        self.assertEqual(len(list(qs[1:3])), 2)
        self.assertEqual(qs.count(), 4)
        with self.assertRaises(IndexError):
            print(qs[99999])
        # Exists
        self.assertEqual(qs.exists(), True)
        self.assertEqual(qs.filter(subject="Test XXX").exists(), False)
        self.assertEqual(
            qs.filter(subject__startswith="Item").delete(),
            [True, True, True, True])