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
Related
Two of my models have datefield and datetimefield. They exist in the same models.py file and I would like to set them to be default upon adding to the database / into existence. More importantly, I would also like to overwrite these fields for generating models to test them.
After some research, I started to use pytz and django.utils timezone. The problem I run into are runtime errors when I try to overwrite them using python's built in datetime (using things like timedelta etc). So I tried converting pytz.utc.localize(), but it complained that the datetime objects I fed it was not naive, but then when I go back to my original version, it still threw the Runtime error. I've found many ways to get over this, mainly using things like date = models.DateField(_("Date"), default=datetime.date.today) which requires import datetime, but the problem here is that I also want to use DateTimeField and now just DateField. So I would use date = models.DateField(_("Date"), default=date.today), but this requires from datetime import date. The imports conflict and the entire thing is messing with me
class SomeTime(models.Model):
moment = models.DateTimeField(default=???, editable=True, blank=True)
class SomeDay(models.Model):
date = models.DateField(default=???, editable=True, blank=True)
I would like to go
m = SomeTime()
m.moment = #some datetime that I set, It should not throw a runtime error
m.save()
d = SomeDay()
d.date = #some date that I set, It should not throw a runtime error
d.save()
As well as simply create these objects, SomeTime must save the current datetime to moment, and SomeDay must save the current date
You're finding problems where there aren't any. If you need to import both datetime and date, then just do so. Or even better, import the datetime module and access both classes within it.
import datetime
class SomeTime(models.Model):
moment = models.DateTimeField(default=datetime.datetime.now, editable=True, blank=True)
class SomeDay(models.Model):
date = models.DateField(default=datetime.date.today, editable=True, blank=True)
Or if you prefer, do from datetime.import datetime, date then default=datetime.now and default=date.today.
you need to import datetime first.
import datetime
then from your code.
now = datetime.datetime.now()
m = SomeTime()
m.moment = now
m.save()
d = SomeDay()
d.date = now.date()
d.save()
For models.DateTimeField use:
from django.utils.dateparse import parse_datetime
# set default date
default_date = parse_datetime('2000-01-01T00:00:00')
class SomeTime(models.Model):
date = models.DateTimeField(default=default_date)
You can update this field with:
from django.utils.timezone import now
filtered_sometime.update(date = now)
# with usage of time delta
filtered_sometime.update(date = now() + relativedelta(months=-1))
To remove the Runtime warning, you can go to your settings.py and comment out "USE_TZ = True". This is just a temporary solution, we would like to find a way to avoid runtime errors altogether while looking at international use
Given a model
class Foo(models.Model):
bar = models.DateTimeField(auto_now_add=True)
When I do
my_foo = Foo.objects.create(bar=yesterday)
Then my_bar.foo is not yesterday but now. I have to do
my_foo = Foo.objects.create()
my_foo.bar = yesterday
my_foo.save()
This didn't use to be the case, but is true for Django 1.8.17
From the docs:
The auto_now and auto_now_add options will always use the date in the default timezone at the moment of creation or update. If you need something different, you may want to consider simply using your own callable default or overriding save() instead of using auto_now or auto_now_add; or using a DateTimeField instead of a DateField and deciding how to handle the conversion from datetime to date at display time.
So you should do that instead
bar = models.DateTimeField(default=date.today)
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.
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.
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)