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

Convert DecimalField to String rather than Float #91

Closed
gsvr opened this issue Jan 17, 2017 · 17 comments · Fixed by #958 or #1083
Closed

Convert DecimalField to String rather than Float #91

gsvr opened this issue Jan 17, 2017 · 17 comments · Fixed by #958 or #1083
Assignees

Comments

@gsvr
Copy link

gsvr commented Jan 17, 2017

DecimalField entries are currently being converted to Float (

@convert_form_field.register(forms.DecimalField)
@convert_form_field.register(forms.FloatField)
def convert_form_field_to_float(field):
return Float(description=field.help_text, required=field.required)
)

Full support for Decimal would be great, but in the meantime I propose that DecimalField should be converted to String instead. Once you've converted a Decimal to a Float, you've probably lost the benefit of why you used Decimal in the first place, since you'll now have values like 3.14000000000000012, rather than 3.14. If it is converted to String, it is simple enough for the user to convert that String back to Decimal, whereas converting from Float to Decimal is not straightforward.

@picturedots
Copy link

As a workaround for this particular problem, I created a Decimal type, and then am explicitly setting that field in the DjangoObjectType class. For example, I created a Decimal type like this

import decimal

from graphene.types import Scalar
from graphql.language import ast

class Decimal(Scalar):
    """ 
    The `Decimal` scalar type represents a python Decimal.
    """
    @staticmethod
    def serialize(dec):
        assert isinstance(dec, decimal.Decimal), (
            'Received not compatible Decimal "{}"'.format(repr(dec))
        )
        return str(dec)
    
    @staticmethod
    def parse_value(value):
        return decimal.Decimal(value)
    
    @classmethod
    def parse_literal(cls, node):
        if isinstance(node, ast.StringValue):
            return cls.parse_value(node.value)

and then explicitly replace the field like this:

class MyModelType(DjangoObjectType):
    my_decimal_field = Decimal()
    class Meta:
        model = MyModel

assuming that I have a Django model MyModel with Decimal field my_decimal_field.

@zbyte64
Copy link
Collaborator

zbyte64 commented Oct 19, 2018

Decimal type landed in graphene: graphql-python/graphene#703

Edit: Appears it isn't released yet but is merged, need graphene>2.1.3

@picturedots
Copy link

Yeah, I finally got around to adding my Decimal type into graphene. It should be possible to fix graphene-django's implementation of DecimalField after the next release of graphene to actually use a Decimal, and it won't be necessary to convert to a String (as per the title of this issue). Note that the JSON output is implemented as string though.

@gsvr
Copy link
Author

gsvr commented Oct 23, 2018

Brilliant, thank you @picturedots!

@gsvr gsvr closed this as completed Oct 23, 2018
@picturedots
Copy link

@gsvr I didn't make the graphene-django change that you noted in form_converter.py above, so not sure if this is issue should be closed. Without that change, it looks like Decimals are still explicitly converted to floats.

@clarkmoody
Copy link

Waiting on this feature as well.

@gsvr gsvr reopened this Mar 5, 2019
@stale
Copy link

stale bot commented Jun 11, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jun 11, 2019
@stale stale bot closed this as completed Jun 18, 2019
@jkimbo jkimbo reopened this Sep 22, 2019
@stale stale bot removed the wontfix label Sep 22, 2019
@stale
Copy link

stale bot commented Dec 21, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Dec 21, 2019
@jkimbo jkimbo removed the wontfix label Dec 26, 2019
@ulgens
Copy link
Collaborator

ulgens commented May 9, 2020

@gsvr @jkimbo Is this still relevant?

@ulgens
Copy link
Collaborator

ulgens commented May 11, 2020

The issue is still relevant. We talked with @jkimbo about how to fix it. My work will be on #958 and i hope to complete in next couple days.

@gsvr
Copy link
Author

gsvr commented May 11, 2020

Thanks @ulgens
I agree that it's still relevant - I've used a workaround in the meantime but this would be a good general improvement imho

@stale
Copy link

stale bot commented Aug 27, 2020

Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale bot added the wontfix label Aug 27, 2020
@gsvr
Copy link
Author

gsvr commented Jan 4, 2021

Thanks to everyone who contributed to resolving this! 👏 👏

@i6mi6
Copy link

i6mi6 commented Jul 9, 2021

Has this been documented in the changelog? It broke our existing app logic because now suddenly we started getting strings rather than floats. Is there a way to default to previous behavior?

@beaugunderson
Copy link

Huge +1 for adding a configuration setting for changing the default behavior here; it looks like this change happened in a minor release? It should have been a major release as it's a breaking change (it broke our codebase as well).

@i6mi6
Copy link

i6mi6 commented Aug 6, 2021

@beaugunderson I ended up forking the repo then modifying it with this commit
i6mi6@d95b19d
In my case the branch name is v2.15.0_decimal then I added it to requirements.txt as follows:

...
graphene==2.1.8
git+git://github.com/i6mi6/graphene-django.git@v2.15.0_decimal#egg=graphene-django
...

@chidimo
Copy link

chidimo commented Nov 15, 2021

As a workaround for this particular problem, I created a Decimal type, and then am explicitly setting that field in the DjangoObjectType class. For example, I created a Decimal type like this

import decimal

from graphene.types import Scalar
from graphql.language import ast

class Decimal(Scalar):
    """ 
    The `Decimal` scalar type represents a python Decimal.
    """
    @staticmethod
    def serialize(dec):
        assert isinstance(dec, decimal.Decimal), (
            'Received not compatible Decimal "{}"'.format(repr(dec))
        )
        return str(dec)
    
    @staticmethod
    def parse_value(value):
        return decimal.Decimal(value)
    
    @classmethod
    def parse_literal(cls, node):
        if isinstance(node, ast.StringValue):
            return cls.parse_value(node.value)

and then explicitly replace the field like this:

class MyModelType(DjangoObjectType):
    my_decimal_field = Decimal()
    class Meta:
        model = MyModel

assuming that I have a Django model MyModel with Decimal field my_decimal_field.

This approach is very helpful.
Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment