In Peewee I have a datetime field defaulted to datetime.datetime.now(). But when inserted, it takes the time the server was started. Why
Asked Answered
I

3

8

When I insert a row, the field is filled with the time when the server was started not the time when the row was inserted. Why is this happening and what is the solution? BTW I am using SQLite.

class LOG(peewee.Model):
    id = peewee.IntegerField(unique=True,primary_key=True)
    timestamp = peewee.DateTimeField(default=datetime.datetime.now())
    log = peewee.CharField()
    by = peewee.IntegerField(default=1)
    class Meta:
        database = database


  LOG.create(log = _log , by = _by)  
  # above statement is called at say 3:00 pm and I started the server at 2:00 pm, then the row is inserted with timestamp of 2pm not 3pm.
Infallible answered 7/10, 2015 at 10:40 Comment(0)
P
36

When your field is loaded by the Python interpreter, it calls datetime.datetime.now() once and only once. So you will always get the same value.

Peewee supports using callables for default args, so rather than calling now() just pass in the function:

timestamp = peewee.DateTimeField(default=datetime.datetime.now)
Perren answered 24/10, 2015 at 5:43 Comment(2)
How to use server side timestamps?Crematory
Found: timestamp = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])Crematory
C
-3

It should be done like this. Override the save method

class myModel(Model):

    name = CharField()
    timestamp = DateTimeField()

    def save(self, *args, **kwargs):
        self.timestamp = datetime.datetime.now()
        super(myModel, self).save(*args, **kwargs)

Works fine after this fix

Chavez answered 18/11, 2016 at 4:51 Comment(1)
This accounts for the case where there's a gap between instantiation and saving, but not for the example above where he was setting the default to the value of datetime.datetime.now() (called when module code loaded) as opposed to the callable datetime.datetime.now.Perren
S
-7

It is taking the compiled time (the time when the server was started)

[edited] because you have used datetime.datetime.now() (with parenthesis) As suggested by @coleifer you can use datetime.datetime.now (without paranthesis) to initiate a run-time call.

[old answer] Overriding the save method will also work

class LOG(peewee.Model):
    id = peewee.IntegerField(unique=True,primary_key=True)
    timestamp = peewee.DateTimeField()
    log = peewee.CharField()
    by = peewee.IntegerField(default=1)
    class Meta:
        database = database

    def save(self, *args, **kwargs):
        self.modified = datetime.datetime.now()
        return super(Something, self).save(*args, **kwargs)

Seems Duplicate of this is there an auto update option for DateTimeField in peewee like TimeStamp in MySQL?

Scofield answered 7/10, 2015 at 10:51 Comment(1)
This is not quite right. Peewee supports callables so you can say default=datetime.datetime.now (no parentheses).Perren

© 2022 - 2024 — McMap. All rights reserved.