Ticket #32118 Add field for 4-bytes floats (RealField/SmallFloatField)

58 views
Skip to first unread message

Zeev Tarantov

unread,
Aug 25, 2022, 2:45:51 PM8/25/22
to Django developers (Contributions to Django itself)
Hi!
I would like to provide an example of why this field is needed.
In PostgreSQL, a floating point literal like 4.6 has type decimal, not binary floating point (see SELECT pg_typeof(4.6)).
When comparing binary floating point values to decimals, the decimal is converted to double precision binary floating point value. This make FloatField work.
But if you have real/float4 fields and you compare them to decimal value, it doesn't work.
Here is an example, with a workaround.

in bar/models.py

from django.db import models
from django.db.models import FloatField

class RealField(FloatField):
    def db_type(self, connection):
        return 'real'

class Thing(models.Model):
    score = RealField(null=False)


and now in shell:

from django.db.models import Value
from django.db.models.functions import Cast
from bar.models import RealField, Thing

Thing(score=4.6).save()

Thing.objects.all()[0].score
4.6

Thing.objects.filter(score=4.6).first()
None

str(Thing.objects.filter(score=4.6).query)
SELECT "bar_thing"."id", "bar_thing"."score" FROM "bar_thing" WHERE "bar_thing"."score" = 4.6

Thing.objects.filter(score=Cast(Value(4.6), RealField())).first()
<Thing: Thing object (1)>

str(Thing.objects.filter(score=Cast(Value(4.6), RealField())).query)
SELECT "bar_thing"."id", "bar_thing"."score" FROM "bar_thing" WHERE "bar_thing"."score" = (4.6)::real

Can Django have a RealField that automatically does the cast?


https://swampup.jfrog.com/?utm_source=email&utm_medium=footer&utm_campaign=emea_sales&utm_term=city-tour-22

Jörg Breitbart

unread,
Aug 25, 2022, 8:52:43 PM8/25/22
to django-d...@googlegroups.com
> Can Django have a RealField that automatically does the cast?

I dont think it is a good idea to go that route in django and add that
as a standard django field, mainly for these reasons:

- FloatField happens to align correctly between pythons only "native"
float type and the chosen db counterparts (as both sides use double
precision under the hood), for a single precision field type that
congruence is not given anymore leading to even more errors
- there are database systems that only do double precision (sqlite I think)
- single precision is an edge case and quite hard to get maths running
with in python (you'd need to shim everything either with ctypes or
numpy, or write your own C-binding)

The last point raises the question - why should django provide a field
type, thats not even represented in its language? To me the django ORM
never felt like a database feature exporter at any cost, but like a
convenient way to interact with databases within typical python
paradigms. Here python clearly falls short lacking a single precision
type, so there are no common use cases at all for this. And mixing
precisions is never a good idea, as your example already showed.

Last but not least - you can still create a single precision float field
yourself, but you should also write a corresponding python type, so you
can do proper maths with it. In your field class you can use
get_db_prep_value or get_prep_value to customize the needed SQL repr
(eg. append inline cast), or use a custom psycopg OID adapter for your
python type.


Cheers,
jerch


Am 25.08.22 um 20:39 schrieb 'Zeev Tarantov' via Django developers
(Contributions to Django itself):
> https://swampup.jfrog.com/?utm_source=email&utm_medium=footer&utm_campaign=emea_sales&utm_term=city-tour-22
> <https://swampup.jfrog.com/?utm_source=email&utm_medium=footer&utm_campaign=emea_sales&utm_term=city-tour-22>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-develop...@googlegroups.com
> <mailto:django-develop...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/068b4121-d28c-4bd7-997e-7fc5d499119en%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/068b4121-d28c-4bd7-997e-7fc5d499119en%40googlegroups.com?utm_medium=email&utm_source=footer>.
Reply all
Reply to author
Forward
0 new messages