def test_transform(self): try: DecimalField.register_lookup(Cos) DecimalModel.objects.create(n1=Decimal('-8.0'), n2=Decimal('0')) DecimalModel.objects.create(n1=Decimal('3.14'), n2=Decimal('0')) objs = DecimalModel.objects.filter(n1__cos__gt=-0.2) self.assertQuerysetEqual(objs, [Decimal('-8.0')], lambda a: a.n1) finally: DecimalField._unregister_lookup(Cos)
def test_transform(self): try: DecimalField.register_lookup(Radians) DecimalModel.objects.create(n1=Decimal('2.0'), n2=Decimal('0')) DecimalModel.objects.create(n1=Decimal('-1.0'), n2=Decimal('0')) objs = DecimalModel.objects.filter(n1__radians__gt=0) self.assertQuerysetEqual(objs, [Decimal('2.0')], lambda a: a.n1) finally: DecimalField._unregister_lookup(Radians)
def test_transform(self): try: DecimalField.register_lookup(Sin) DecimalModel.objects.create(n1=Decimal('5.4'), n2=Decimal('0')) DecimalModel.objects.create(n1=Decimal('0.1'), n2=Decimal('0')) objs = DecimalModel.objects.filter(n1__sin__lt=0) self.assertQuerysetEqual(objs, [Decimal('5.4')], lambda a: a.n1) finally: DecimalField._unregister_lookup(Sin)
def test_transform(self): try: DecimalField.register_lookup(Ceil) DecimalModel.objects.create(n1=Decimal('3.12'), n2=Decimal('0')) DecimalModel.objects.create(n1=Decimal('1.25'), n2=Decimal('0')) objs = DecimalModel.objects.filter(n1__ceil__gt=3) self.assertQuerysetEqual(objs, [Decimal('3.12')], lambda a: a.n1) finally: DecimalField._unregister_lookup(Ceil)
class MyMax(Max): output_field = DecimalField() def as_sql(self, compiler, connection): copy = self.copy() copy.set_source_expressions(copy.get_source_expressions()[0:1]) return super(MyMax, copy).as_sql(compiler, connection)
def as_postgresql(self, compiler, connection): # Cast FloatField to DecimalField as PostgreSQL doesn't support the # following function signatures: # - LOG(double, double) # - MOD(double, double) output_field = DecimalField(decimal_places=sys.float_info.dig, max_digits=1000) clone = self.copy() clone.set_source_expressions([ Cast(expression, output_field) if isinstance( expression.output_field, FloatField) else expression for expression in self.get_source_expressions() ]) return clone.as_sql(compiler, connection)
def test_combine_different_types(self): msg = 'Expression contains mixed types. You must set output_field.' qs = Book.objects.annotate(sums=Sum('rating') + Sum('pages') + Sum('price')) with self.assertRaisesMessage(FieldError, msg): qs.first() with self.assertRaisesMessage(FieldError, msg): qs.first() b1 = Book.objects.annotate(sums=Sum( F('rating') + F('pages') + F('price'), output_field=IntegerField())).get(pk=self.b4.pk) self.assertEqual(b1.sums, 383) b2 = Book.objects.annotate(sums=Sum( F('rating') + F('pages') + F('price'), output_field=FloatField())).get(pk=self.b4.pk) self.assertEqual(b2.sums, 383.69) b3 = Book.objects.annotate(sums=Sum( F('rating') + F('pages') + F('price'), output_field=DecimalField())).get(pk=self.b4.pk) self.assertEqual(b3.sums, Approximate(Decimal("383.69"), places=2))
def __init__(self, expression, *, output_field=None, **extra): super().__init__(expression, output_field=output_field or DecimalField(), **extra)
def _resolve_output_field(self): has_decimals = any( isinstance(s.output_field, DecimalField) for s in self.get_source_expressions()) return DecimalField() if has_decimals else FloatField()