Using "rounding" on a DecimalField

526 views
Skip to first unread message

akr...@servicechannel.com

unread,
Jan 19, 2018, 7:57:02 AM1/19/18
to Django REST framework
Hey all! We recently discovered "rounding" for the DecimalField type (DecimalField API) and thought it was a perfect option to use for rounding latitude and longitude fields that may have varying lengths. After multiple implementation attempts, we can't quite get it to work right. It seems that the model validations are firing before the rounding can take place on the serializer.

This is my first post to this group, so I'm not sure what level of detail I should include. That being said, I'll be verbose =)

Any help would be greatly appreciated! 

Thanks,
Andy



Serializer

class AddressSerializer(BaseCreateSerializer):

    id = serializers.UUIDField(read_only=True)
    latitude = serializers.DecimalField(max_digits=8, decimal_places=5, rounding=ROUND_DOWN)
    longitude = serializers.DecimalField(max_digits=8, decimal_places=5, rounding=ROUND_DOWN)

    class Meta:
        model = Address
        fields = ('id', 'label', 'name', 'locality', 'region',
            'country', 'postalcode', 'latitude', 'longitude')

Model

class Address(BaseContactModel):
    """
    Not every field is required to be a valid address, but at
    least one "non-foreign-key" field must be populated.

    ForeignKey Reqs: either the `location` or `person` FK must be
    populated, but not both.
    """
    name = models.CharField(max_length=500, blank=True, null=True)
    locality = models.CharField(max_length=50)
    region = models.CharField(max_length=50)
    region_a = models.CharField(max_length=12)
    postalcode = models.CharField(max_length=12, blank=True, null=True)
    country = models.CharField(max_length=55)
    country_a = models.CharField(max_length=3, default="US")
    latitude = models.DecimalField(decimal_places=5, max_digits=8)
    longitude = models.DecimalField(decimal_places=5, max_digits=8)
    label = models.CharField(max_length=700)

    def __str__(self):
        return "id: {}; name: {}; locality: {}; region: {}; country: {}".format(
                self.id, self.name, self.locality, self.region, self.country)

Test

class AddressTests(APITestCase):

    def setUp(self):
        self.person = create_person()
        self.address = create_address(self.person)
        self.client.login(username=self.person.username, password=PASSWORD)

    def test_truncates_latitude_longitude(self):
        address = Address.objects.last()
        serializer = AddressSerializer(address)
        data = serializer.data
        data.update({
            'latitude': 123.456789101112,
            'longitude': 123.456789101112,
        })
        response = self.client.post('/api/admin/addresses/', data, format='json')
        self.assertEqual(response.data['latitude'], 123.456789)

Test Output

======================================================================
FAIL: test_truncates_latitude_longitude (contact.tests.test_views.AddressTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/akrier/github/bsrs/bsrs-django/bigsky/contact/tests/test_views.py", line 136, in test_truncates_latitude_longitude
    self.assertEqual(response.data['latitude'], 123.456789)
AssertionError: ['Ensure that there are no more than 8 digits in total.'] != 123.456789

----------------------------------------------------------------------



Reply all
Reply to author
Forward
0 new messages