Search code examples
pythonpython-2.7django-ormfreezegun

Freezegun does not work on django orm create_at field


I am trying to use freezegun for unittest:

    class Customer(models.Model):
        created_at = models.DateTimeField(default=datetime.now, null=True)


    from freezegun import freeze_time

    with freeze_time(datetime(2020, 9, 9, 9), tz_offset=9):
            customer = Customer.objects.create()
            print 'created at', customer.created_at

    # prints: created at 2020-11-27 19:54:11.994688

So it seems like the freezetime isn't working for django orm for some reason. I am unable to do Customer.objects.create(created_at=...) in the function I am trying to test.

How can I correctly set the created_at time using freezegun?

Many thanks in advance.


Solution

  • The problem is that you pass the function directly, hence when the freezegun overrides the datetime.now attribute, that has no impact on the references to the old function.

    An alternative might be to make a custom function where you each time retrieve the attribute:

    def current_time():
        return datetime.now()
    
    class Customer(models.Model):
            created_at = models.DateTimeField(default=current_time, null=True)

    But Django actually already has a way to use the time of creation: you can specify auto_now_add=True [Django-doc]:

    class Customer(models.Model):
            created_at = models.DateTimeField(auto_now_add=True, null=True)

    This will also set the field to editable=False [Django-doc] such that, by default, it does not show up in a ModelForm.