-3

In django, I'm validating a date:

from datetime import date
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError

if start_date < date.today():
    raise ValidationError(
        _('%(start_date)s must be on or after today.'),
        params={'start_date': start_date},
    )

where start_date is a datetime instance.

What do I need to write in place of s in %(start_date)s in order to format the date nicely; preferably as dd-mmm-yyyy?

Harjit Singh
  • 45
  • 10

1 Answers1

1

You can use strftime(...) method as,

def validate_date(start_date):
    if start_date < date.today():
        raise ValidationError(
            _('%(start_date)s must be on or after today.'),
            params={'start_date': start_date.strftime("%d-%b-%Y")},
        )

    return start_date

You will get the exception as,

django.core.exceptions.ValidationError: ['01-Jan-2020 must be on or after today.']


You can see the full set for format code that supported by strftime(...) method here, strftime() and strptime() Format Codes


Update-1

You can use the str.format() method as,

def validate_date(start_date):
    if start_date < date.today():
        raise ValidationError(
            _("{:%d-%b-%Y} must be on or after today.".format(start_date))
        )

    return start_date

Update-2

as @Justin Ezequiel mention in his comment, you can use the f-string as

def validate_date(start_date):
    if start_date < date.today():
        raise ValidationError(
            _(f"{start_date:%d-%b-%Y} must be on or after today.")
        )

    return start_date
JPG
  • 82,442
  • 19
  • 127
  • 206
  • Thank you. But is there a way of doing this without changing the type of `start_date` in `params`? Sonmething like `%(start_date)d-%(start_date)%b-%(start_date)Y must be on or after today.'? – Harjit Singh May 22 '21 at 16:13
  • Are you into something like my *"Update-1"* section? – JPG May 22 '21 at 17:02
  • Not really. What I really want is a replacement for `s` in `%(start_date)s` in my program snippet. It might not be possible of course. Perhaps your way is the best way?! – Harjit Singh May 24 '21 at 09:17
  • You can't replace the ***`%s`*** with something else. In this situation, Django uses the ***`%`*** style string formatting ([old-style `PyFormat`](https://pyformat.info/)) to format the string – JPG May 24 '21 at 09:42
  • Personally, I'm wondering how the `str.format()` or `datetime.strftime()` methods are becoming *not succinct* to you :O – JPG May 24 '21 at 09:45
  • I'm nervous about changing the type of start_date in params. – Harjit Singh May 24 '21 at 09:52
  • In the end, all you need is ***a string***, nothing more, nothing less. The ***`%s`*** is something that converts to string with the given object, just like calling `str(any_dt_obj)` – JPG May 24 '21 at 09:57
  • If you are uncomfortable to call the `strftime` in the parameters, you can go for the `Update-1` and `Update-2`. To my best knowledge, this is a dead-end – JPG May 24 '21 at 09:59
  • Thank you very much for your time. Had a chat with a colleague in the end (on this site too as Bathsheba) - completely agreed with you. Said that the %s as it appears in the ValidationError constructor is purely a Django thing, not a Python thing per se, and in the Django source code it maps to str. – Harjit Singh May 25 '21 at 09:24