简体   繁体   中英

How to change DECIMAL_SEPARATOR and THOUSAND_SEPARATOR used in serializers in django rest framework?

How can I change the DECIMAL_SEPARATOR and THOUSAND_SEPARATOR used to serialize DecimalField? Or how can I make django-rest-framework automatically use the right ones depending on l10n?

My situation:

I'm using django rest framework ModelSerializer to serialize a model like the following one:

class House(models.Model):
    name = models.CharField(max_length=200)
    area = models.DecimalField(max_digits=7, decimal_places=2)

The serializer.py code is the following:

class HouseSerializer(serializers.ModelSerializer):
    class Meta:
        model = House

And in settings.py I have properly set the localization settings that work fine in templates:

LANGUAGE_CODE = 'en-us'
USE_I18N = True
USE_L10N = True
LANGUAGES = (
    ('es', _('Spanish')),
    ('en', _('English')),
)

USE_THOUSAND_SEPARATOR = True

LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)

I use a ModelViewSet:

class HouseViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.HouseSerializer
    queryset = House.objects.all()

And finally, I have the urls.py with the i18n part in the url:

router = DefaultRouter()
router.register(r'house', viewsets.HouseViewSet)

urlpatterns += i18n_patterns('',
    url(r'^api/', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
)

When I ask for data (GET) in example.com/ en /api/house/, I get the decimal field correctly formated:

{
    "name": "House in L.A.", 
    "area": "1,234.50", 
} 

However, When I ask for data (GET) in example.com/ es /api/house/, I get the decimal field with the same format, which is wrong in Spanish. I need to get:

{
    "name": "Casa en L.A.", 
    "area": "1.234,50", 
} 

How can I do it? Thank you!

I know this question is five years old, and the other answers work, but as its on the top of a google search for the subject, my two cents.

1) Check if 'django.middleware.locale.LocaleMiddleware' sits in MIDDLEWARE in settings.py. Obvious, but I spend a lot of time wondering why it did not work.

2) You could also do:

area = serializers.DecimalField(max_digits=7, decimal_places=2, localize=True)

Which looks less 'hacky'.

Looks like DRF does not support number localization. In Django this is solved in two ways( more about this ):

  1. Provide an additional argument in the form's field
  2. Use special tags or filter in the templates

Neither of them is not used in DRF.

But django have helpful function in django.utils.format - number_format . You can use it to solve your problem.

For example:

from django.utils.formats import number_format


class HouseSerializer(serializers.ModelSerializer):
    area = serializers.SerializerMethodField('area_localize')

    class Meta:
        model = House

    def area_localize(self, obj):
        return number_format(obj.area)

The previous answer from Alex Lisovoy is correct, but since I have null=True in my models (that I omitted from the question for simplification), I was getting wrong output values when area=null. Therefore, I used a slightly different code, that I show here.

My real models are:

class House(models.Model):
    name = models.CharField(max_length=200)
    area = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)

The exact code I used is:

from django.utils.formats import number_format

class HouseSerializer(serializers.ModelSerializer):
    area = serializers.SerializerMethodField('area_localize')

    class Meta:
        model = House

    def area_localize(self, obj):
        if obj.area:
            return number_format(obj.area)
        else: 
            return None

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM