def test_spanning_relations_with_custom_lookup_in_search_fields(self): hype = Group.objects.create(name='The Hype') concert = Concert.objects.create(name='Woodstock', group=hype) vox = Musician.objects.create(name='Vox', age=20) Membership.objects.create(music=vox, group=hype) # Register a custom lookup on IntegerField to ensure that field # traversing logic in ModelAdmin.get_search_results() works. IntegerField.register_lookup(Exact, 'exactly') try: m = ConcertAdmin(Concert, custom_site) m.search_fields = ['group__members__age__exactly'] request = self.factory.get('/', data={SEARCH_VAR: '20'}) cl = m.get_changelist_instance(request) self.assertCountEqual(cl.queryset, [concert]) request = self.factory.get('/', data={SEARCH_VAR: '21'}) cl = m.get_changelist_instance(request) self.assertCountEqual(cl.queryset, []) finally: IntegerField._unregister_lookup(Exact, 'exactly')
def test_spanning_relations_with_custom_lookup_in_search_fields(self): hype = Group.objects.create(name='The Hype') concert = Concert.objects.create(name='Woodstock', group=hype) vox = Musician.objects.create(name='Vox', age=20) Membership.objects.create(music=vox, group=hype) # Register a custom lookup on IntegerField to ensure that field # traversing logic in ModelAdmin.get_search_results() works. IntegerField.register_lookup(Exact, 'exactly') try: m = ConcertAdmin(Concert, custom_site) m.search_fields = ['group__members__age__exactly'] request = self.factory.get('/', data={SEARCH_VAR: '20'}) cl = m.get_changelist_instance(request) self.assertCountEqual(cl.queryset, [concert]) request = self.factory.get('/', data={SEARCH_VAR: '21'}) cl = m.get_changelist_instance(request) self.assertCountEqual(cl.queryset, []) finally: IntegerField._unregister_lookup(Exact, 'exactly')
class IntegerFieldFloatRounding(object): """ Allow floats to work as query values for IntegerField. Without this, the decimal portion of the float would always be discarded. """ def get_prep_lookup(self): if isinstance(self.rhs, float): self.rhs = math.ceil(self.rhs) return super(IntegerFieldFloatRounding, self).get_prep_lookup() class IntegerGreaterThanOrEqual(IntegerFieldFloatRounding, GreaterThanOrEqual): pass IntegerField.register_lookup(IntegerGreaterThanOrEqual) class IntegerLessThan(IntegerFieldFloatRounding, LessThan): pass IntegerField.register_lookup(IntegerLessThan) class DecimalComparisonLookup(object): def as_sqlite(self, compiler, connection): lhs_sql, params = self.process_lhs(compiler, connection) rhs_sql, rhs_params = self.process_rhs(compiler, connection) params.extend(rhs_params) # For comparisons whose lhs is a DecimalField, cast rhs AS NUMERIC
class IntegerFieldFloatRounding(object): """ Allow floats to work as query values for IntegerField. Without this, the decimal portion of the float would always be discarded. """ def get_prep_lookup(self): if isinstance(self.rhs, float): self.rhs = math.ceil(self.rhs) return super(IntegerFieldFloatRounding, self).get_prep_lookup() class IntegerGreaterThanOrEqual(IntegerFieldFloatRounding, GreaterThanOrEqual): pass IntegerField.register_lookup(IntegerGreaterThanOrEqual) class IntegerLessThan(IntegerFieldFloatRounding, LessThan): pass IntegerField.register_lookup(IntegerLessThan) class In(FieldGetDbPrepValueIterableMixin, BuiltinLookup): lookup_name = 'in' def process_rhs(self, compiler, connection): db_rhs = getattr(self.rhs, '_db', None) if db_rhs is not None and db_rhs != connection.alias: raise ValueError( "Subqueries aren't allowed across different databases. Force "