Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accepting localized Date input on Django REST framework

Have a form for submitting date in russian, typical input will be like:

"1 апреля 2020"

Also have a serializer:

class CartSerializer(serializers.Serializer):
    ...
    delivery_date = serializers.DateTimeField(input_formats=['%d %B %Y',])

At settings.py have:

LANGUAGE_CODE = 'ru'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True

When i send delivery_date to rest API it returns an error:

{"delivery_date":["Datetime has wrong format. Use one of these formats instead: DD [January-December] YYYY."]}

Is it possible in DRF to accept non-english Date value?

Upd (on @GlennDJ comment):

my view.py

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response    
from .serializers import CartSerializer

@api_view(['GET', 'POST'])
def add_tocart_api(request):
    ...
    serializer = CartSerializer(data=request.data)
    print(serializer)
    if serializer.is_valid():
        print(serializer.data)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Didn't use django forms here just sent {delivery_date: "22 Октября 2021"} from frontend via ajax (js fetch)

like image 948
art_hq Avatar asked May 24 '26 15:05

art_hq


1 Answers

If you're OK with using a 3rd party library, you can subclass rest_framework.serializers.DateTimeField and replace its .datetime_parser property with one that uses arrow for conversion:

Implementation:

import arrow
from rest_framework import serializers


class ArrowDateTimeField(serializers.DateTimeField):

    def __init__(self, format=empty, input_formats=None, default_timezone=None, **kwargs):
        locale = kwargs.pop('locale', None)
        super().__init__(format, input_formats, default_timezone, **kwargs)
        if locale:
            self.datetime_parser = lambda dtstr, fmt: arrow.get(dtstr, fmt, locale=locale)

Usage:

from { whichever module you put it } import ArrowDateTimeField  


adtf = ArrowDateTimeField(input_formats=['D MMMM YYYY'], locale='ru-ru')

print(adtf.to_internal_value("1 апреля 2020"))
# .to_internal_value method will reach for .datetime_parser internally

please notice you must provide Arrow's own tokens to input_format, they are different from Python standards.

like image 127
VBobCat Avatar answered May 27 '26 05:05

VBobCat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!