How to use the encoder for `values()` so to behave as if it's still using DRF encoder?

10 views
Skip to first unread message

TJ Simmons

unread,
Nov 3, 2019, 6:02:52 AM11/3/19
to Django REST framework
I am using DRF and i have a situation where I have too many database calls.

So I used `values()` for one of the serializers to reduce the number of calls.


I am of course not sure if this is the best way to solve it. In Tom Christie's piece he mentioned about using values here https://www.dabapps.com/blog/api-performance-profiling-django-rest-framework/

I quote

>4. You don't always need to use serializers.
>
>For performance critical views you might consider dropping the serializers entirely and simply use .values() in your database queries. If you're using hyperlinked representations or other complex fields you might find you also need to do some post processing on the data structures before returning them in the response. REST framework is designed to make this easy.

Ok so far so good. One API i have issues with went from 800+ database queries to 16. I consider that a success.

Then, when I run my unit tests, things fail.

Why? Because the datetime format expected was wrong. So I used DRF's own JSOEncoder which fixed this issue but broke another thing.

I also have decimal values which usually converts to STRING because of the default COERCE_DECIMAL_TO_STRING setting. See https://github.com/encode/django-rest-framework/blob/b26db128135fcd10c890213d8d56af8cf0a171a0/docs/api-guide/settings.md#coerce_decimal_to_string

Now unfortunately this setting applies the coercion at the serializer level. Not the encoder level.

SO if i use `JSONEncoder().default(this_is_a_decimal)` i will get back float. Not string. So I had to write my own encoder.


My question is is this something that can be improved within the DRF library? if so, I will be happy to send a PR.

I wasn't sure and I didn't want to pollute the github issues hence i posted here for advice.

Thank you

Jason

unread,
Nov 3, 2019, 7:42:59 AM11/3/19
to Django REST framework
Nice work!

I think this was an explicit decision by Tom back in 2014.  Using https://github.com/encode/django-rest-framework/commit/040bfcc09c851bb3dadd60558c78a1f7937e9fbd for reference, you can see DecimalField was re-written to use string coercion, though it wasn't a setting at the time.  In the same commit, JSONEncoder changed the output of a Decimal from str to float

I'm not sure having the JSONEncoder know about COERCE_TO_STRING is a good thing.  It is True by default, which could cause some major unexpected behavior in JSONEncoder by taking that into consideration.  I think your approach of making a custom encoder for your project is the best direction.

I do have some comments about your encoder.

https://github.com/encode/django-rest-framework/blob/335054a5d36b352a58286b303b608b6bf48152f8/rest_framework/utils/encoders.py  is the DRF implementation.  It seems you basically duplicate the datetime encoding, so it seems to me you could just use the decimal conditional check.
Reply all
Reply to author
Forward
0 new messages