Reputation: 889
I have a class with a US cent value. When I serialize it I want to be able to convert it to a dynamically specified other currency. So the class looks like this:
class Evaluation(models.Model):
sum_in_cents = models.IntegerField()
def converted_sum_in_cents(currency_code):
currency_code = currency_code.upper()
CurrencyConverter().convert(self.sum_in_cents / 100, 'USD', currency_code)
... #other stuff
And it has a standard serializer that currently ignores that function:
class EvaluationSerializer(serializers.ModelSerializer):
class Meta:
model = Evaluation
fields = '__all__'
depth = 1
So how, when using the serializer, should I get the currency_code
argument to the converted_sum_in_cents method? (it's passed as a query string in the view)
I've got as far as learning that I can pass a context
object when initialising my serialiser and that serialiser functions can access data within that, but I can't see how to include the output of those functions as a serialiser field. I've also found this thread, which is my fallback plan, but both that thread's author and I are suspicious that if that were the right way of doing something that seems like it must come up a lot, DRF would have included a lot less hacky pathway to doing it. So am I just thinking about this wrong?
Upvotes: 0
Views: 797
Reputation: 889
I've found a way:
When instantiating the EvaluationSerializer class, I optionally pass in a context argument as mentioned in the OP, described here.
All methods of the class then have access to that object. The part I was missing is described in this StackOverflow answer:
Create a custom method field on the object, and define a method called get_<custom_field_name>
to set the value. So the Evaluation class looks like this:
class EvaluationSerializer(serializers.ModelSerializer):
converted_cost_per_output = serializers.SerializerMethodField()
def get_converted_cost_per_output(self, evaluation):
currency_code = self.context['currency'].upper()
return CurrencyConverter().convert(evaluation.cents_per_output / 100, 'USD', currency_code)
(and there's no method defined on the model)
Upvotes: 1