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

Error when accessing serializer.data that contains price-related fields (For example, CheckoutSerializer) #188

Closed
rollue opened this issue Sep 25, 2019 · 4 comments

Comments

@rollue
Copy link

rollue commented Sep 25, 2019

I overrode the checkoutserializer(added an extra sender_info field), so I was writing some tests on the serializer itself.

# test_serializers.py
...
cs = CheckoutSerializer(data=payload, context={"request": request})
cs.is_valid(raise_exception=True)
data = cs.data  <- error raised
...

The raised error was decimal.InvalidOperation: [<class 'decimal.ConversionSyntax'>].

I error message was not clear at first, so I did some digging in, and I found that the error was raised within the serializer's to_representation block.

...
# django-rest-framework(=3.10.3)'s serializers.py
...
...
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
    ret[field.field_name] = None
else:
    ret[field.field_name] = field.to_representation(attribute)  <- error here line 526

It seems the attribute is Price class return by the following line, in oscarapi's checkoutserializer's validate method.

total = OrderTotalCalculator().calculate(basket, shipping_charge)

So the attribute looks like this:

Price(currency='USD', excl_tax=Decimal('10000.00'), incl_tax=Decimal('10000.00'), tax=Decimal('0.00'))

So in order to access the serializer.data, one might have to handle decimal fields(total in this checkoutserializer) individually by using attribute.incl_tax as a parameter to to_representation method, when dealing with price-related fields. Or you can probably handle this at field level too.

This error may be trivial because it does NOT affect the core logic and purpose of the CheckoutSerializer - so this may not have to be fixed.

But I'm leaving this issue as a reference for someone who might need to access serializer.data like me. :) (FYI, you can still access serializer.validated_data without any extra error handling)

@maerteijn
Copy link
Member

maerteijn commented Oct 21, 2019

It indeed looks like the OrderTotalCalculator is returning a Price object and not a Decimal value.

My first thought is that the current CheckoutSerializer total field definition is wrong and should be replaced by a PriceSerializer

But I need more investigation for this, thanks for reporting!

maerteijn pushed a commit that referenced this issue Oct 22, 2019
…rice

Use a different field for the calculated order total. See also #188
maerteijn pushed a commit that referenced this issue Oct 22, 2019
Use a different field for the calculated order total. See also #188
maerteijn pushed a commit that referenced this issue Oct 22, 2019
Use a different field for the calculated order total. See also #188
maerteijn pushed a commit that referenced this issue Oct 22, 2019
Use a different field for the calculated order total. See also #188
@maerteijn
Copy link
Member

As already thought, the input type for the total field is a Decimal, in the validate method we change this to a Price instance returned by the OrderTotalCalculator. We should not do this, see the pull request.

BTW, accessing the data attribute is a bit funky here as the CheckoutSerializer does not really fit into the normal" Django Rest Framework serializing objects" way of working.

See also the comment by Tom Christie.

Access validated_data instead, (which was also broken but fixed with this pull request)

@maerteijn
Copy link
Member

@mhoonjeon The pull request is merged, see the comments above. Thanks you your input, closing this issue now

@rollue
Copy link
Author

rollue commented Oct 29, 2019

@maerteijn Sorry I checked this feedback a little late; I use gitlab for work most of the times and I only check github from time to time :(. Anyways, thanks for the feedback and I really appreciate how much you guys have put into this open source project. Keep up the good work!!

dudleyhunt86 added a commit to dudleyhunt86/django-api-ovrride that referenced this issue Oct 7, 2022
Use a different field for the calculated order total. See also django-oscar/django-oscar-api#188
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants