question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Modelserializer in django rest_framework serializes MeasurementField as FloatField

See original GitHub issue

hi,

I have the following field in my model: MeasurementField(measurement=Weight, unit_choices=(('kg','kg'),('lb','lb'),))

which serializes as a FloatField() in django rest framework using serializers.ModelSerializer. This FloatField() then does not accept a Mass() object so I land on a TypeError.

Anyone with an idea how to rewrite the serializers to_represantation and to_internal_value to handle this error? I tried this which works for the representation part:

 def to_representation(self, obj):
        return {
            'weight': obj.weight.value,
            'unit': obj.weight.unit}

But I cannot get the to_internal_value to work. Besides, there are other fields in the model which I have to rewrite if I use this approach. Thanks in advance for any suggestion!

Could it be an enhancement to include a serializerField in the MeasurementField definition?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:6

github_iconTop GitHub Comments

2reactions
SOMGERcommented, Oct 1, 2018

I looked into this further and I think the problem is that there is no MultiValueField among the serializers.Fields in DRF, like there is in forms.Fields, so DRF cannot handle what is in your forms.py line 99-110. Maybe this is a problem more for DRF then for your package. At least, I couldn’t find anything that would correspond to forms.MultiValueField in DRF. I ended up defining a custom field like so:

class WeightField(serializers.Field):

    def to_representation(self, obj):
        ret = {"weight": obj.value,
                "unit": obj.unit}
        return ret

    def to_internal_value(self, data):
        unit = data[-2:]
        value = data[:-2]
        if unit == 'kg':
            return Weight(kg=value)
        else:
            if unit == 'lb':
                value_mass = Weight(lb=value)
                return value_mass

I still need to add validation that no other units are entered in the form field, but it works. Only found this solution yesterday.

1reaction
codingjoecommented, Oct 4, 2018

how about something like this?

>>> data = "1gram"
>>> units = Weight.UNITS.keys() | Weight.ALIAS.keys()
>>> pattern = re.compile(r'^(?P<value>\d+)(?P<unit>(%s))$' % '|'.join(units))
>>> match = pattern.match(data)
>>> if match is None:
...     raise ValueError("%s is not a valid %s" % (data, Weight.__name__))
...
>>> kwargs = {match.group('unit'): match.group('value')}
>>> Weight(**kwargs)
Mass(g=1.0)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Serializer fields - Django REST framework
Serializer fields handle converting between primitive values and internal datatypes. They also deal with validating input values, ...
Read more >
Numeric fields in serializers - Django REST Framework
This article revolves around Numeric Fields in Serializers in Django REST Framework. There are three major fields – IntegerField, FloatField ...
Read more >
How to serialize creation with Django Rest Framework ...
I can't comment due to low rep but here's the function from the classyDRF def create(self, request, *args, **kwargs): serializer ...
Read more >
Handling Model Relationships in Django Rest Framework
Make a note of the related_field = “ingredients" attribute. This is required for the serializer for Product to get access to the related ......
Read more >
Creating a REST API with Django REST Framework
The serializer accepts the JSON data, deserializes it into a concrete object and then serializes it again, to return a response. You can...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found