Date defaults to Django webserver start date rather than to the default method parameter

I’ve stumbled on something unexpected, it is probably something basic I’m misunderstanding either in Python or Django.

I have a static method in my model class to return the date provided by the user or alternatively return today’s date:

    @staticmethod
    # By default return today's date or the date provided
    def get_start_date(**kwargs):
        startDate = kwargs.get('startDate', datetime.date.today())
        return startDate

I decided to rewrite it such that the method has the startDate as a default parameter. However, instead of defaulting to today’s date it defaults to the date when the Django webserver was first started. Why would this be the case? The method is executed, I’ve confirmed that the startDate was not provided in the call, even when a variable which I know for certain isn’t used anywhere else in the code is entered in the argument, it still returns the date Django was first ran.

    def get_start_date(startDate=datetime.date.today(), notUsed=datetime.date.today(), **kwargs):
        print(startDate, notUsed, datetime.date.today())
        return startDate

    >>> 2022-06-23 2022-06-23 2022-06-24

>Solution :

Python’s default arguments are evaluated once when the function is defined, not each time the function is called. This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

So, change your function definition to

def my_function(start_date=datetime.date.today()):
    # do something

to

def my_function(start_date=None):
    if start_date is None:
        start_date = datetime.date.today()
    # do something

Leave a Reply