different behaviour of datetime.datetime object before vs after save

37 views
Skip to first unread message

Alex Kleider

unread,
Sep 24, 2015, 2:31:23 AM9/24/15
to django...@googlegroups.com
I'm baffled by the fact that the __str__ method of an instance fails
before the instance is saved but works fine afterwards.

The relevant snippet from my models.py file:
class Journal(models.Model):
date = models.DateTimeField(default=timezone.now)
user = models.CharField(max_length=24)
description = models.CharField(max_length=256)
def __str__(self):
ret = [" #{:0>3} on {:<12} by {}."
.format(self.id,
self.date.strftime('%Y-%m-%d %H:%M'),
self.user)]
for line in self.description.split('\n'):
ret.append(" {}".format(line))
return '\n'.join(ret)

Here's the result of some experimentation using the shell:
(venv)alex@x301:~/Py/debk$ ./manage.py shell
Python 3.4.0 (default, Jun 19 2015, 14:18:46)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from journal.models import Journal
>>> j = Journal(user='Alex', description='Test entry')
>>> j
Traceback (most recent call last):
File "<console>", line 1, in <module>
File
"/home/alex/Py/venv/lib/python3.4/site-packages/django/db/models/base.py",
line 496, in __repr__
u = six.text_type(self)
File "/home/alex/Py/debk/journal/models.py", line 22, in __str__
self.user)]
TypeError: non-empty format string passed to object.__format__
>>> j.save()
>>> j
<Journal: #005 on 2015-09-24 06:11 by Alex.
Test entry>
>>>

I don't understand why saving would change the behavior of an instance.
I'd like my code to be able to display such an instance before a
decision is made whether or not to save it.
I'd be grateful if anyone could explain what's happening and perhaps
suggest a way to use the __str__ method before saving.

Thanks in advance for any help.

Alex K

James Schneider

unread,
Sep 24, 2015, 3:04:12 AM9/24/15
to django...@googlegroups.com


> I'm baffled by the fact that the __str__ method of an instance fails
> before the instance is saved but works fine afterwards.
>
> The relevant snippet from my models.py file:
> class Journal(models.Model):
>     date = models.DateTimeField(default=timezone.now)

Check the docs on the use of 'default'. The value or callable in this case is used when the object is created by saving the object instance to the database. Granted, the wording should probably be more specific since there is an overlap of meanings for creating the object.

https://docs.djangoproject.com/en/1.8/ref/models/fields/#default

It doesn't particularly make sense to do what you are doing in the first place. You are attributing a time stamp to a volatile piece of data in memory, and in reality it is already gone from memory by the time the user sees it since the response cycle has ended, and is likely being dynamically rebuilt upon the next request cycle in response to form data. What if the user takes 30 minutes to decide to click the submit button and finalize saving the object to the database?

Which moment of time would you want to capture: a) the time the object is created in memory and displayed to the user or b) the moment the object is saved to a non-volatile location like the DB? Most times you'll want the latter since that's when an actual change occurred.

However, if you truly want to catch the moment that the object instance was created in memory, you'll need to add date=timezone.now to your Journal() call instead of relying on the default value of the model field, which only is populated at the point where save() is called and no previous value exists. Obviously if this is part of a confirmation form, you'll need to pass the original timestamp along through the form as well, or you'll wind up with option b) above anyway.

-James

Reply all
Reply to author
Forward
0 new messages