def test_order_related_ids(self): z = Zoo(name='hoi') z.save() a9 = Animal.objects.create(zoo_id=z.id, name='a9').id a0 = Animal.objects.create(zoo_id=z.id, name='a0').id a2 = Animal.objects.create(zoo_id=z.id, name='a2').id a6 = Animal.objects.create(zoo_id=z.id, name='a6').id a7 = Animal.objects.create(zoo_id=z.id, name='a7').id a5 = Animal.objects.create(zoo_id=z.id, name='a5').id a4 = Animal.objects.create(zoo_id=z.id, name='a4').id a3 = Animal.objects.create(zoo_id=z.id, name='a3').id a8 = Animal.objects.create(zoo_id=z.id, name='a8').id a1 = Animal.objects.create(zoo_id=z.id, name='a1').id with CustomOrdering(Animal, 'name'): response = self.client.get('/zoo/{}/?with=animals'.format(z.id)) self.assertEqual(response.status_code, 200) returned_data = jsonloads(response.content) self.assertEqual(returned_data['data']['animals'], [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9]) # Check ordering on complex OrderBy expression. with CustomOrdering(Animal, Upper('name').asc(), '-id'): response = self.client.get('/zoo/{}/?with=animals'.format(z.id)) self.assertEqual(response.status_code, 200) returned_data = jsonloads(response.content) self.assertEqual(returned_data['data']['animals'], [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9]) # Complex order by with desc on an F field with an operation on it with CustomOrdering(Animal, OrderBy(Length(F('name')), descending=True), '-name'): response = self.client.get('/zoo/{}/?with=animals'.format(z.id)) self.assertEqual(response.status_code, 200) returned_data = jsonloads(response.content) self.assertEqual(returned_data['data']['animals'], [a9, a8, a7, a6, a5, a4, a3, a2, a1, a0]) # Nested complex order by with CustomOrdering(Animal, Reverse(Upper('name')), 'id'): response = self.client.get('/zoo/{}/?with=animals'.format(z.id)) self.assertEqual(response.status_code, 200) returned_data = jsonloads(response.content) self.assertEqual(returned_data['data']['animals'], [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9]) with CustomOrdering(Animal, '-name'): response = self.client.get('/zoo/{}/?with=animals'.format(z.id)) self.assertEqual(response.status_code, 200) returned_data = jsonloads(response.content) self.assertEqual(returned_data['data']['animals'], [a9, a8, a7, a6, a5, a4, a3, a2, a1, a0])
def test_expressions(self): author = Author.objects.annotate(backward=Reverse(Trim('name'))).get( pk=self.john.pk) self.assertEqual(author.backward, self.john.name[::-1]) with register_lookup(CharField, Reverse), register_lookup(CharField, Length): authors = Author.objects.all() self.assertCountEqual(authors.filter(name__reverse__length__gt=7), [self.john, self.elena]) self.assertCountEqual(authors.exclude(name__reverse__length__gt=7), [self.python])
def test_basic(self): authors = Author.objects.annotate(backward=Reverse('name')) self.assertQuerysetEqual( authors, [ ('John Smith', 'htimS nhoJ'), ('Élena Jordan', 'nadroJ anelÉ'), ('パイソン', 'ンソイパ'), ], lambda a: (a.name, a.backward), ordered=False, )
def test_building_filter_with_many_annotated_qs_merges_the_annotations( data_fixture): user = data_fixture.create_user() table = data_fixture.create_database_table(user=user) text_field = data_fixture.create_text_field(table=table, order=1, name="name") another_text_field = data_fixture.create_text_field(table=table, order=2, name="surname") model = table.get_model() row_1 = model.objects.create( **{ f"field_{text_field.id}": "name", f"field_{another_text_field.id}": "other" }) model.objects.create( **{ f"field_{text_field.id}": "eman", f"field_{another_text_field.id}": "extra" }) model.objects.create( **{ f"field_{text_field.id}": "not_name", f"field_{another_text_field.id}": "not_other", }) builder = FilterBuilder(filter_type=FILTER_TYPE_AND) builder.filter( AnnotatedQ( annotation={"reversed_name": Reverse(f"field_{text_field.id}")}, q={f"field_{text_field.id}": "name"}, )) builder.filter( AnnotatedQ( annotation={"upper_name": Upper(f"field_{text_field.id}")}, q={f"field_{text_field.id}": "name"}, )) builder.filter(Q(reversed_name="eman")) builder.filter(Q(upper_name="NAME")) queryset = builder.apply_to_queryset(model.objects) assert queryset.count() == 1 assert row_1 in queryset
def test_building_filter_with_many_annotated_qs_merges_the_annotations( data_fixture): user = data_fixture.create_user() table = data_fixture.create_database_table(user=user) text_field = data_fixture.create_text_field(table=table, order=1, name='name') another_text_field = data_fixture.create_text_field(table=table, order=2, name='surname') model = table.get_model() row_1 = model.objects.create( **{ f'field_{text_field.id}': 'name', f'field_{another_text_field.id}': 'other' }) model.objects.create( **{ f'field_{text_field.id}': 'eman', f'field_{another_text_field.id}': 'extra' }) model.objects.create( **{ f'field_{text_field.id}': 'not_name', f'field_{another_text_field.id}': 'not_other' }) builder = FilterBuilder(filter_type=FILTER_TYPE_AND) builder.filter( AnnotatedQ( annotation={'reversed_name': Reverse(f'field_{text_field.id}')}, q={f'field_{text_field.id}': 'name'})) builder.filter( AnnotatedQ(annotation={'upper_name': Upper(f'field_{text_field.id}')}, q={f'field_{text_field.id}': 'name'})) builder.filter(Q(reversed_name='eman')) builder.filter(Q(upper_name='NAME')) queryset = builder.apply_to_queryset(model.objects) assert queryset.count() == 1 assert row_1 in queryset
def test_can_invert_an_annotated_q(data_fixture): user = data_fixture.create_user() table = data_fixture.create_database_table(user=user) text_field = data_fixture.create_text_field(table=table, order=1, name="name") another_text_field = data_fixture.create_text_field(table=table, order=2, name="surname") model = table.get_model() model.objects.create( **{ f"field_{text_field.id}": "name", f"field_{another_text_field.id}": "other" }) row_2 = model.objects.create( **{ f"field_{text_field.id}": "eman", f"field_{another_text_field.id}": "extra" }) row_3 = model.objects.create( **{ f"field_{text_field.id}": "not_name", f"field_{another_text_field.id}": "not_other", }) builder = FilterBuilder(filter_type=FILTER_TYPE_AND) q_to_invert = AnnotatedQ( annotation={"reversed_name": Reverse(f"field_{text_field.id}")}, q={f"reversed_name": "eman"}, ) builder.filter(~q_to_invert) queryset = builder.apply_to_queryset(model.objects) assert queryset.count() == 2 assert row_2 in queryset assert row_3 in queryset
def test_can_invert_an_annotated_q(data_fixture): user = data_fixture.create_user() table = data_fixture.create_database_table(user=user) text_field = data_fixture.create_text_field(table=table, order=1, name='name') another_text_field = data_fixture.create_text_field(table=table, order=2, name='surname') model = table.get_model() model.objects.create( **{ f'field_{text_field.id}': 'name', f'field_{another_text_field.id}': 'other' }) row_2 = model.objects.create( **{ f'field_{text_field.id}': 'eman', f'field_{another_text_field.id}': 'extra' }) row_3 = model.objects.create( **{ f'field_{text_field.id}': 'not_name', f'field_{another_text_field.id}': 'not_other' }) builder = FilterBuilder(filter_type=FILTER_TYPE_AND) q_to_invert = AnnotatedQ( annotation={'reversed_name': Reverse(f'field_{text_field.id}')}, q={f'reversed_name': 'eman'}) builder.filter(~q_to_invert) queryset = builder.apply_to_queryset(model.objects) assert queryset.count() == 2 assert row_2 in queryset assert row_3 in queryset
#!/usr/bin/env python from django.db.models.functions import Reverse from .models import MyModel """ https://docs.djangoproject.com/en/dev/ref/models/database-functions/#reverse class Reverse(expression, **extra) """ qs = MyModel.objects.annotate(backward=Reverse('name')) for r in qs.all(): print(r.backward)
def test_null(self): author = Author.objects.annotate(backward=Reverse('alias')).get( pk=self.python.pk) self.assertEqual( author.backward, '' if connection.features.interprets_empty_strings_as_nulls else None)