Django Rest Framework - How do i actually use a custom date format?

Hi there,
using drf, i developed a simple api for an internal project.
I got asked to change the format of the date field from the ISO format “%Y-%m-%d” to the format ‘%d.%m.%Y’.
I read and re-read the documentation, jumped from forum and discussion, but i can’t find a working solution.
The project structure is:
project/

api/

    init.py
    formats/

        init.py
        it/

            init.py
            formats.py

    migrations/
    admin.py
    apps.py
    ...

backend/

    init.py
    asgi.py
    settings.py
    urls.py
    wsgi.py

in project/backend/settings.py i have set
LANGUAGE_CODE = ‘it’
FORMAT_MODULE_PATH = [‘api.formats’,]

and in project/api/formats/it/formats.py i have set
DATE_INPUT_FORMATS = [
‘%d/%m/%y’,
‘%d/%m/%Y’,
‘%d.%m.%Y’,
‘%d.%m.%y’,
‘%Y-%m-%d’,
# etc
]

but still doesn’t work, and fails my request, asking for a date in format ‘%Y-%m-%d’
The documentation doesn’t help really much undestanding how to properly customize the format, as this “The locale-dictated format has higher precedence and will be applied instead.” tries to imply that customization is impossible.

Django version: 5.1.4
djangorestframework version: 3.15.2

Welcome @federicobucciero !

You ask:

Are you talking about the format of the date field that you are going to accept as a submission, or that you are going to provide in the response? (Or both?)

In either case, what we need to see are the serializers you are using for this.

Hi!
Short answer: both.

Long answer: The process is the following…
I send an excel file to my api, and using pandas and openpyxl it reads some sheets, in the specific case this

some_stuff = {
            'a_string': sheet['G1'].value,
            'another_string': sheet['K1'].value,
            'a_string_too': sheet['I1'].value,
            'you_will_never_guess_what_i_am': sheet['J1'].value,
            'date': sheet['H1'].value.strftime("%d.%m.%Y"),
        }

i then pass this data to the serializer

class SomeStuffSerializer(serializers.ModelSerializer):
    class Meta:
        model = SomeStuff
        fields = '__all__'

after validating this and others istances, i create a response like this

response = {
        #some info
        'another_date': datetime.datetime.today().strftime("%d%m.%Y"),
    }

because this response will be used in a form to pre-compile some fields, based on some of the information extracted from the excel file.

Given that you ask for the serializers, i guess that the problem is in it?
Anyway thx for your time!

Yes and no.

Are you saying that this doesn’t work?
If so, then my guess would be that sheet['H1'].value is not being recognized as a Date object, and what you would need to do depends upon what the value is that you’re actually receiving.

What are you getting as a result of this? (Note: you’re missing a period between %d and %m.)

The code worked fine when istead of the d.m.Y format i was using the Y/m/d format, but the date is still read accordingly.
The problem is that the validation of the serializer fails, asking always for the Y/m/d format.

It’s like the serializer either:

  1. doesn’t check the format module path i added in settings
  2. the path i added is somehow wrong(?)

Please good sir, help me in the ardous quest of date formatting.

1 Like

Please post the complete code involved, along with the complete error message, the full serializers, and any traceback that you may be getting. Do not edit-down, anonymize, summarize, or otherwise alter the code you’re trying to run.

Also, we are talking about two distinct operations here - what you’re reading from the excel file and what you’re generating as output. Please specify which operations when describing somethign is “not working”.

For example:

Which code?

What date?

What are the results?

What serializer?

What validation?

What is the specific error message(s) you are receiving?

The more accurate and detailed information you provide, the better chance we have of getting to the underlying issue.

I tried to explain myself as best as possible, anyway the steps are simple.
This is the post request that creates a PO given an excel file

def post(self, request):
        """ Create a PianoEsecutivo and its related data from an uploaded file. """
        file = request.FILES.get('file')
        if not file:
            return Response({"error": "No file provided."}, status=status.HTTP_400_BAD_REQUEST)

        try:
            # Parse the Excel file
            piano_esecutivo_data = parse_excel_file(file)

            # Validate all data
            piano_esecutivo_serializer = PianoEsecutivoSerializer(
                data=piano_esecutivo_data)

            if not piano_esecutivo_serializer.is_valid():
                return Response(piano_esecutivo_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

           # ...other stuff, not involded in the error

where the method to parse the file is this:

def parse_excel_file(file):
    """ Parse the provided Excel file and return structured data for PianoEsecutivo, ArticoloDettaglio, and ArticoloDei. """
    try:
        # Load the Excel file and select the sheet
        sheet = load_workbook(file, data_only=True)['Allegato 4']

        # Extract data for the piano_esecutivo
        piano_esecutivo = {
            'oda': sheet['G1'].value,
            'lotto_type': sheet['K1'].value,
            'pa_name': sheet['I1'].value,
            'soc_appalto': sheet['J1'].value,
            'request_date': sheet['H1'].value.strftime("%d.%m.%Y"),
            'doc_type': 'PED' if int(sheet['G1'].value) % 2 == 0 else 'PEP'
        }

The response is this:

request_date	[ "La data è in un formato errato. Usa uno dei seguenti formati: YYYY-MM-DD." ]

The serializer is the one i posted before, the same is for the project structure.
Just for clarification, could you provide me for reference an example project where the custom formatting works?

I believe one of the issues here may be that you’re trying to use a ModelSerializer with non-model data. So my guess is that the data type of the field request_date that you are submitting to the serializer is not a match with the corresponding field in the model. (You haven’t shown either the model or the serializer here as requested, so we have no way to confirm that.)

If you want to use a ModelSerializer, then I would suggest you create an instance of the model from the data to ensure that the data types are correct.

Otherwise, I suggest you create a regular serializer that can handle the data as it’s being submitted.

Side note: There are people here who try to help solve issues with DRF, but this forum is not an official DRF support channel. You may get faster results if you post your question through one of the resources listed in the Support section of the DRF docs.

As i stated in the question to begin with, mine is not a code problem. Using the ISO format all was working just as intended. The model is well written, the serializer does indeed have model data, everything is fine.
I just need to know, given that in the newer version of django the setting USE_L10N got removed, how do i add a custom formatting to my code properly given that the documentation on this matter is not very clear?
It would be faster to provide an example project structure and the settings to correctly apply the formatting

According to your first post, it looks like you defined DATE_INPUT_FORMATS in the localization file for it language. This is what django uses to parse input dates from form fields.

Here, you’re using Django Rest Framework which does not rely on such localization parameter. As stated in the documentation for such serializer field, the input formats are taken from the DATE_INPUT_FORMATS setting, which, in the context of DRF, means the “DATE_INPUT_FORMATS” entry of the REST_FRAMEWORK setting.