Django datetime issues (default=datetime.now()) - python

I have the below db model:
from datetime import datetime
class TermPayment(models.Model):
# I have excluded fields that are irrelevant to the question
date = models.DateTimeField(default=datetime.now(), blank=True)
I add a new instance by using the below:
tp = TermPayment.objects.create(**kwargs)
My issue: all records in database have the same value in date field, which is the date of the first payment. After the server restarts, one record has the new date and the other records have the same as the first. It looks as if some data is cached, but I can't find where.
database: mysql 5.1.25
django v1.1.1

it looks like datetime.now() is being evaluated when the model is defined, and not each time you add a record.
Django has a feature to accomplish what you are trying to do already:
date = models.DateTimeField(auto_now_add=True, blank=True)
or
date = models.DateTimeField(default=datetime.now, blank=True)
The difference between the second example and what you currently have is the lack of parentheses. By passing datetime.now without the parentheses, you are passing the actual function, which will be called each time a record is added. If you pass it datetime.now(), then you are just evaluating the function and passing it the return value.
More information is available at Django's model field reference

Instead of using datetime.now you should be really using from django.utils.timezone import now
Reference:
Documentation for django.utils.timezone.now
so go for something like this:
from django.utils.timezone import now
created_date = models.DateTimeField(default=now, editable=False)

From the documentation on the django model default field:
The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.
Therefore following should work:
date = models.DateTimeField(default=datetime.now,blank=True)

David had the right answer. The parenthesis () makes it so that the callable timezone.now() is called every time the model is evaluated. If you remove the () from timezone.now() (or datetime.now(), if using the naive datetime object) to make it just this:
default=timezone.now
Then it will work as you expect:
New objects will receive the current date when they are created, but the date won't be overridden every time you do manage.py makemigrations/migrate.
I just encountered this. Much thanks to David.

The datetime.now() is evaluated when the class is created, not when new record is being added to the database.
To achieve what you want define this field as:
date = models.DateTimeField(auto_now_add=True)
This way the date field will be set to current date for each new record.

datetime.now() is being evaluated once, when your class is instantiated. Try removing the parenthesis so that the function datetime.now is returned and THEN evaluated. I had the same issue with setting default values for my DateTimeFields and wrote up my solution here.

From the Python language reference, under Function definitions:
Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that that same “pre-computed” value is used for each call.
Fortunately, Django has a way to do what you want, if you use the auto_now argument for the DateTimeField:
date = models.DateTimeField(auto_now=True)
See the Django docs for DateTimeField.

The answer to this one is actually wrong.
Auto filling in the value (auto_now/auto_now_add isn't the same as default). The default value will actually be what the user sees if its a brand new object. What I typically do is:
date = models.DateTimeField(default=datetime.now, editable=False,)
Make sure, if your trying to represent this in an Admin page, that you list it as 'read_only' and reference the field name
read_only = 'date'
Again, I do this since my default value isn't typically editable, and Admin pages ignore non-editables unless specified otherwise. There is certainly a difference however between setting a default value and implementing the auto_add which is key here. Test it out!

In Django 3.0 auto_now_add seems to work with auto_now
reg_date=models.DateField(auto_now=True,blank=True)

if you need only DateField try this
date = models.DateField(auto_now=False, auto_now_add=False, null=True, blank=True)
if you need Both Date and Time try this
date = models.DateTimeField(auto_now_add=True, null=True, blank=True)

Related

What's equivalent to Django's auto_now, auto_now_add in SQLAlchemy?

In Django, we can use these 2 parameters when making a date column:
DateField.auto_now Automatically set the field to now every time the
object is saved. Useful for “last-modified” timestamps. Note that the
current date is always used; it’s not just a default value that you
can override.
DateField.auto_now_add Automatically set the field to now when the
object is first created. Useful for creation of timestamps. Note that
the current date is always used; it’s not just a default value that
you can override.
How to do this in SQLAlchemy?
Finally, after checking the SQLAlchemy doc, this should be the way:
Column('created_on', DateTime, default=datetime.datetime.now)
Column('last_updated', DateTime, onupdate=datetime.datetime.now)
doc here:
http://docs.sqlalchemy.org/en/latest/core/defaults.html#python-executed-functions
It's still possible to use the following:
enter_date = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
On update also sqlalchemy set the current date at the time the data updates.

save time.time() in django model

I want to have some kind of timestsamp for updating of models. The problem is that mysql timestamp is only in 1 sec resolution, so if I use DateTime with auto_add_now this is not fine enough for me.
I thought of using float field and to assign it to time.time() on every update. This is a model where I use update using QuerySet.update()
model MyModel:
last_update = models.FloatField(default=time.time)
I then take care of updating last_update before any save (all my calls goes through central location, so I can do this explicitly in the creation), e.g something like:
m = MyModel(..,last_update=time.time())
or when I do bulk update,
m = MyModel.objects.filter(....).update(last_update_time=time.time())
Are there any issues with this approach of saving float and order by it?
Just to clarify, I'm aware of DateTimeField option with auto_now=True, the problem is that this gives me 1 second resolution since it is mapped to date time field in MYSQL which is 1 sec resolution (I'm using MYSQL 5.5)
I think you can use DateField.auto_now, and the field will be updated each time the object gets saved. For example last_update = models.DateTimeField(auto_now = True).
You can read the documentation here, as you can see that Field option is intended to archive exactly what you want.
Also you can override the save method as you can see there and update the last_update field as you prefer.
Personally I recommend the first approach because of simplicity, there is also a third option using signals but I guess that can get so confusing.
from datetime import datetime
class Model(models.Model):
date_created = models.DateTimeField()
date_modified = models.DateTimeField()
def save(self):
if self.date_created == None:
self.date_created = datetime.now()
self.date_modified = datetime.now()
super(Model, self).save()

Best way to get future event from a date and a time attribute

In one of my Django application I have an object with both a date and a time attribute, and i don't wish to use a datetime single attribute.
For the sake of example let's call this object "Meeting":
class Meeting(models.Model):
publication_date = models.DateField()
publication_time = models.TimeField()
Now I would like to get all the Meetings in the future given the current time
I am currently using this query:
Meeting.objects.filter(publication_date__gte=datetime.date.today()).exclude(publication_date=
datetime.date.today(),
publication_time__lt =
datetime.datetime.now()).order_by('publication_date',
'publication_time')
But I feel like there might be a more efficient way
Nope that would be the correct way to do it given the constraint of not using a datetime field. Why you don't want to use a datetime field I don't know.

Datetime.now() abnormality - Python

I'm serving a Python app through Django. Within the app I'm storing the classic "created" field within a few tables.
This is how the field looks like within the Django form:
created = models.DateTimeField(blank=True, default=datetime.now())
Unfortunately, datetime.now() is not accurate. In fact in the database I have sets of rows with the exact same timestamp.
The datetime.now() value seems to change every 30-45 minutes.
My Django app is served on Windows Server 2005 behind IIS6.
Help would be amazing!
This is a common newbie mistake, unfortunately. You have called the datetime.now() method in the definition - this means the default will be the time at which the definition was executed, ie when your server process starts up.
You need to pass the callable instead:
created = models.DateTimeField(blank=True, default=datetime.now)
ie without the calling brackets.
(Or, just use auto_now_add=True).
because datetime.now() is being called when your module is initialised and that value is being used for the default.
You want to use the auto_now_add=True parameter
created = models.DateTimeField(auto_now_add=True)
edit: no need for 'blank' if you're setting the auto option.
You don't have auto_now or auto_now_add fields set to True. Consequently, the default value is what's filled in on the form. When the form is sent to the browser. Of course there will be duplicates.
http://docs.djangoproject.com/en/1.2/ref/models/fields/#datetimefield

Django DateField default options

I have a model which has a date time field:
date = models.DateField(_("Date"), default=datetime.now())
When I check the app in the built in django admin, the DateField also has the time appended to it, so that if you try to save it an error is returned. How do I make the default just the date? (datetime.today() isn't working either)
This is why you should always import the base datetime module: import datetime, rather than the datetime class within that module: from datetime import datetime.
The other mistake you have made is to actually call the function in the default, with the (). This means that all models will get the date at the time the class is first defined - so if your server stays up for days or weeks without restarting Apache, all elements will get same the initial date.
So the field should be:
import datetime
date = models.DateField(_("Date"), default=datetime.date.today)
Your mistake is using the datetime module instead of the date module. You meant to do this:
from datetime import date
date = models.DateField(_("Date"), default=date.today)
If you only want to capture the current date the proper way to handle this is to use the auto_now_add parameter:
date = models.DateField(_("Date"), auto_now_add=True)
However, the modelfield docs clearly state that auto_now_add and auto_now will always use the current date and are not a default value that you can override.
date = models.DateTimeField(default=datetime.now, blank=True)
I think a better way to solve this would be to use the datetime callable:
from datetime import datetime
date = models.DateField(default=datetime.now)
Note that no parenthesis were used. If you used parenthesis you would invoke the now() function just once (when the model is created). Instead, you pass the callable as an argument, thus being invoked everytime an instance of the model is created.
Credit to Django Musings. I've used it and works fine.
DateField/DateTimeField.auto_now_add
Automatically set the field to now when the object is first created. Useful for creation of timestamps. Note that the current date is always used; it’s not just a default value that you can override. So even if you set a value for this field when creating the object, it will be ignored.
Source: Django
doc
This should do the trick:
models.DateTimeField(_("Date"), auto_now_add = True)
You could also use lambda. Useful if you're using django.utils.timezone.now
date = models.DateField(_("Date"), default=lambda: now().date())
django hint:
HINT: It seems you set a fixed date / time / datetime value as default for this field. This may not be what you want. If you want to have the current date as default, use django.utils.timezone.now

Categories