Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django FloatField is incorrectly labeled as float (32-bit) OpenAPI format rather than double (64-bit) #674

Closed
johnthagen opened this issue Mar 7, 2022 · 5 comments
Labels
enhancement New feature or request fix confirmation pending issue has been fixed and confirmation from issue reporter is pending

Comments

@johnthagen
Copy link
Contributor

johnthagen commented Mar 7, 2022

Consider a Django model:

class MyModel(Model):
    value = models.FloatField(null=True, blank=True)

From the Django docs

A floating-point number represented in Python by a float instance.

float's in Python are effectively always 64-bit double precision floats (it may be possible on some bespoke embedded platforms like MicroPython they are something else, but those are out of scope for Django usage).

But drf-spectacular, generates a schema for this FloatField of:

        value:
          type: number
          format: float
          nullable: true

According to the OpenAPI 3 spec, the correct format for this should be:

        value:
          type: number
          format: double
          nullable: true

It's likely many users have not hit this because some common client languages (e.g. Python and JavaScript/TypeScript) only have one float/number type so this would not have an impact on the generated client code.

However, a language such as C# does have two different floating point types, float and double. OpenAPI Generator using the csharp-netcore generator parses the drf-spectacular schema and uses 32-bit C# float instead of 64-bit double. This means that the client will lose precision that otherwise is stored in Django.

Example C# output:

        [DataMember(Name = "value", EmitDefaultValue = true)]
        public float? Value { get; set; }

Expected output:

        [DataMember(Name = "value", EmitDefaultValue = true)]
        public double? Value { get; set; }
@johnthagen johnthagen changed the title Django FloatField is incorrectly labeled as float (32-bit) OpenAPI format rather than double (64-bit) Django FloatField is incorrectly labeled as float (32-bit) OpenAPI format rather than double (64-bit) Mar 7, 2022
@tfranzel
Copy link
Owner

tfranzel commented Mar 8, 2022

Hey John,

excellent find! This must have slipped through the crack due to the imprecise naming.

CPython uses double internally and postgres, mysql and oracle Django DB adapters all map to double precision (https://github.com/django/django/blob/fac3dd7f390d372736e05974cc5c3ef1a3768fbb/django/db/backends/postgresql/base.py#L86)

So it makes sense to change the default mapping. One note however, format is a "free" field and you can put anything you want. OpenAPI deems it only informational. So not sure the code generator overreaches a bit in the case of c#.

@johnthagen
Copy link
Contributor Author

@tfranzel Would it be possible to get a release with this fix?

@tfranzel
Copy link
Owner

@johnthagen it's coming very soon. just dealing with some loose ends.

@tfranzel tfranzel added enhancement New feature or request fix confirmation pending issue has been fixed and confirmation from issue reporter is pending labels Mar 17, 2022
@tfranzel
Copy link
Owner

closing this issue for now. feel free to comment if anything is missing or not working and we will follow-up.

@johnthagen
Copy link
Contributor Author

Sorry for the late reply. I tested 0.22.0 and can confirm this issue is fixed!

Thanks! ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fix confirmation pending issue has been fixed and confirmation from issue reporter is pending
Projects
None yet
Development

No branches or pull requests

2 participants