Re: Change `to_python` and `to_url` to be class methods on path converters

2022-08-25 Thread 'Adam Johnson' via Django developers (Contributions to Django itself)
I can see the appeal of allowing you to have fewer classes, but I don't
think that's a good thing in itself. Keeping responsibilities separate
("convert slugs to/from URL's" versus "be a slug") is a generally desirable
property.

This change would also complicate the URL parsing process: it would need to
check whether the methods are class or instance level, and instantiate the
converter or not. We wouldn't want to force all converters to move to use
classmethods as that would be a backwards incompatible change, requiring a
deprecation cycle.

On Wed, Aug 24, 2022 at 7:35 PM Petter friberg 
wrote:

> Hi,
>
> I ran in to the situation of wanting `to_python` and `to_url` be decorated
> with `@classmethod` to avoid having to declare an additional (kind of
> no-op) class with those 2 methods.
>
> Given that I have a couple of custom python data structures that can be
> encoded into path params, it would be slightly more cleaner if my custom
> class(es) would be the ones declaring `def to_python` and `def to_url` to
> comply with the path converter interface. Rather than having some
> additional `class Converter`.
>
> Below follows an invented example, where I pretend to have some product
> slug composed of a slugged name and integer code. Imagine seeing something
> like “white-socks-123456789” in a URL.
>
> ```
> class Slug:
> regex = r".+"
>
> def __init__(self, slugged_name, sku):
> self.slugged_name = slugged_name
> self.sku = sku
>
> @classmethod
> def to_python(cls, value):
> name, _, sku = value.rpartition("-")
> if not name:
> raise ValueError("invalid name segment")
>
> try:
> sku = int(sku)
> except ValueError as exc:
> raise ValueError("sku needs to be a number") from exc
>
> return cls(name, sku)
>
> @classmethod
> def to_url(cls, slug):
> return f"{slug.slugged_name}-{slug.sku}"
>
>
> register_converter(Slug, "my-slug")
> ```
>
> Could changing the converter interface be something to consider?
> At least I couldn’t see any obvious problems with expecting these 2
> methods as `@classmethod` (or even `@staticmethod`?) instead. But I could
> very well be missing something.
>
> Thanks!
> Petter
>
> --
> 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-developers+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/a43092e4-34a1-403a-beef-a2c4cac710ebn%40googlegroups.com
> 
> .
>

-- 
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-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAMyDDM3PTv0Bre7aBDWW%3DFx1j3Az2GihPBqJ3tetKjf3cXtVkA%40mail.gmail.com.


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

2022-08-25 Thread 'Zeev Tarantov' via 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()


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?


-- 
 


-- 
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-developers+unsubscr...@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.


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

2022-08-25 Thread Jörg Breitbart

> 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):

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()


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 



--
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-developers+unsubscr...@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 
.


--
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-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/23df220a-0545-23ac-9d36-2aae70a9f682%40netzkolchose.de.