Are we dropping auto_now and auto_now_add for 1.0?

4,566 views
Skip to first unread message

SmileyChris

unread,
Apr 1, 2007, 8:02:04 PM4/1/07
to Django developers
I'm not sure if there's a ticket for this, but I remember talk about
it being an unnecessary wart which was going to be removed eventually.
Is it in the 1.0 plan?

Adrian Holovaty

unread,
Apr 1, 2007, 8:50:20 PM4/1/07
to django-d...@googlegroups.com

Yes, I'd like to drop those two options.

auto_now can be accomplished with "default=datetime.datetime.now", and
auto_now_add can be accomplished with a custom save() method.

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com

Jacob Kaplan-Moss

unread,
Apr 1, 2007, 8:52:48 PM4/1/07
to django-d...@googlegroups.com
On 4/1/07, SmileyChris <smile...@gmail.com> wrote:

Oh, please, yes!

I'd be inclined just to remove 'em wholesale and let things fail
loudly, but if someone wants to work up a patch that issues a
validation warning (and otherwise does nothing when those params are
there) that's probably the right approach.

Jacob

Russell Keith-Magee

unread,
Apr 1, 2007, 9:00:42 PM4/1/07
to django-d...@googlegroups.com
On 4/2/07, Adrian Holovaty <holo...@gmail.com> wrote:
>
> On 4/1/07, SmileyChris <smile...@gmail.com> wrote:
> > I'm not sure if there's a ticket for this, but I remember talk about
> > it being an unnecessary wart which was going to be removed eventually.
> > Is it in the 1.0 plan?
>
> Yes, I'd like to drop those two options.
>
> auto_now can be accomplished with "default=datetime.datetime.now", and
> auto_now_add can be accomplished with a custom save() method.

What about LazyDate? It seems to me that given
"default=datetime.datetime.now" is legal, LazyDate can be deprecated
as well.

Yours
Russ Magee %-)

Jacob Kaplan-Moss

unread,
Apr 1, 2007, 9:08:57 PM4/1/07
to django-d...@googlegroups.com
On 4/1/07, Russell Keith-Magee <freakb...@gmail.com> wrote:
> What about LazyDate? It seems to me that given
> "default=datetime.datetime.now" is legal, LazyDate can be deprecated
> as well.

Yeah, I'd like to get rid of LazyDate, too.

Jacob

Malcolm Tredinnick

unread,
Apr 1, 2007, 9:11:17 PM4/1/07
to django-d...@googlegroups.com

Is there an easy way to say "today - 3 days" just using the datetime
module? I can't think of one off the top of my head that isn't as
complex as LazyDate(), but that may be because it's Monday.

At the moment LazyDate is useful in limit_choices_to and as a default
value. I'd vote to move it into django/utils/dates.py so that it's more
visible (it feels wrong in models/__init__.py, but that may just be my
bad taste), but I'd like to keep it. Otherwise I'm pretty sure I'm going
to end up rewriting it for myself.

Cheers,
Malcolm

Russell Keith-Magee

unread,
Apr 1, 2007, 9:21:40 PM4/1/07
to django-d...@googlegroups.com
On 4/2/07, Malcolm Tredinnick <mal...@pointy-stick.com> wrote:
>
> Is there an easy way to say "today - 3 days" just using the datetime
> module? I can't think of one off the top of my head that isn't as
> complex as LazyDate(), but that may be because it's Monday.

How about:

lambda : datetime.now() + datetime.timedelta(days=3)

Yours,
Russ Magee %-)

Malcolm Tredinnick

unread,
Apr 1, 2007, 9:23:34 PM4/1/07
to django-d...@googlegroups.com
On Mon, 2007-04-02 at 11:11 +1000, Malcolm Tredinnick wrote:
[...]

> At the moment LazyDate is useful in limit_choices_to and as a default
> value.

Scrub that last part. Wishful thinking on my part. It can't really be
used as a default at the moment, because it doesn't have a __call__
method.

Malcolm


Malcolm Tredinnick

unread,
Apr 1, 2007, 9:26:46 PM4/1/07
to django-d...@googlegroups.com

Yep, you're right. Must be Monday. :-(

I withdraw my objection. Nuke it.

Malcolm

Honza Král

unread,
Apr 1, 2007, 9:37:12 PM4/1/07
to django-d...@googlegroups.com
On 4/2/07, Adrian Holovaty <holo...@gmail.com> wrote:
>
> On 4/1/07, SmileyChris <smile...@gmail.com> wrote:
> > I'm not sure if there's a ticket for this, but I remember talk about
> > it being an unnecessary wart which was going to be removed eventually.
> > Is it in the 1.0 plan?
>
> Yes, I'd like to drop those two options.
>
> auto_now can be accomplished with "default=datetime.datetime.now", and
> auto_now_add can be accomplished with a custom save() method.

well, if I see this correctly, both have to be implemented in save().
Default will only be used if you don't supply a value, where auto_now
is used every time and cannot be overridden.

that said, I would be happy without them as well ;)

+1 on removing those options

>
> Adrian
>
> --
> Adrian Holovaty
> holovaty.com | djangoproject.com
>
> >
>


--
Honza Král
E-Mail: Honza...@gmail.com
ICQ#: 107471613
Phone: +420 606 678585

trbs

unread,
Apr 2, 2007, 12:52:48 PM4/2/07
to Django developers
On Apr 2, 2:50 am, "Adrian Holovaty" <holov...@gmail.com> wrote:

> On 4/1/07, SmileyChris <smileych...@gmail.com> wrote:
>
> > I'm not sure if there's a ticket for this, but I remember talk about
> > it being an unnecessary wart which was going to be removed eventually.
> > Is it in the 1.0 plan?
>
> Yes, I'd like to drop those two options.
>
> auto_now can be accomplished with "default=datetime.datetime.now", and
> auto_now_add can be accomplished with a custom save() method.
>
> Adrian

It could be just me, but although i don't mind losing auto_*, it don't
look very DRY in save.

I know it's only a few lines (like 4 ? for both options, not using
default= for sake of keeping the logic together) but when lots of
models
have a cre_date and mod_date, those lines are repeated over and over
again in save().

Maybe a decorator or the dispatcher can help for all the models with
automaticly filled cre and mod_date's. This could also be combined
with
things like last_modified_by_user and created_by_user. Cause to me it
seems these are all standard (housekeeping) tasks which you would like
to associate with a model and not repeat the code for it in every
model.

But i could be missing the point entirely :) Malcolm's 'It's Monday'
comment could apply to me too ;)


Brian Beck

unread,
Apr 6, 2007, 2:15:09 PM4/6/07
to Django developers
On Apr 2, 12:52 pm, "trbs" <v.oostv...@gmail.com> wrote:
> It could be just me, but although i don't mind losing auto_*, it don't
> look very DRY in save.
>
> I know it's only a few lines (like 4 ? for both options, not using
> default= for sake of keeping the logic together) but when lots of
> models
> have a cre_date and mod_date, those lines are repeated over and over
> again in save().

I agree. Using default= in place of auto_now_add is fine, but writing
a save() for every model that needs auto_now is just annoying. A
shortcut would be nice.

David Larlet

unread,
Apr 6, 2007, 2:39:25 PM4/6/07
to django-d...@googlegroups.com
2007/4/6, Brian Beck <exo...@gmail.com>:

I agree with Brian.

Regards,
David

Brian Beck

unread,
Apr 6, 2007, 4:08:22 PM4/6/07
to Django developers
Did people feel that save() was a better solution because it's already
a place where you have to put equivalent functionality for other
fields? I don't know why, but defining my own save() always seems like
a "big deal" that should be reserved for more complex stuff.

What about a new attribute for all fields, something like:
default_condition, where:

- The default is set if default_condition(current_value) is True.
- By default, default_condition is `lambda value: value is None`, this
mimicks current behavior.

So:
# default_condition is True when created_date is None
created_date = models.DateTimeField(default=datetime.now)

# default_condition is always True, equivalent to auto_now=True
updated_date = models.DateTimeField(default=datetime.now,
default_condition=lambda
value: True)

And it's useful for other fields:

minimum_of_zero = models.IntegerField(default=0,
default_condition=lambda
value: value < 0)

Sean Perry

unread,
Apr 6, 2007, 10:03:14 PM4/6/07
to django-d...@googlegroups.com

seems like it should be as easy as a function in contrib somewhere:

def auto_now(amodel):
if not amodel.id:
amodel.created = datetime.datetime.now()
else:
amodel.modified = datetime.datetime.now()

super(type(amodel), amodel).save()

and in your model you have:

save = contrib.auto_now

When you have to add code to your save() method you could still call
auto_now(self).

Jacob Kaplan-Moss

unread,
Apr 6, 2007, 10:12:04 PM4/6/07
to django-d...@googlegroups.com
> seems like it should be as easy as a function in contrib somewhere:
[snip]

Another option is a trivial field subclass::

class AutoDateTimeField(models.DateTimeField):
def pre_save(self, model_instance, add):
return datetime.datetime.now()

Jacob

Joseph Perla

unread,
Apr 6, 2007, 10:19:38 PM4/6/07
to django-d...@googlegroups.com
+1.  Follows DRY.  An AutoDateTimeField is very common.
j

doug.na...@gmail.com

unread,
Apr 6, 2007, 10:53:50 PM4/6/07
to Django developers
I made this suggestion on the django board.

@auto_now('updatted_on')
@auto_add_now('submitted_date')
def save(self):
super(MyModel).save()

I even have started coding it as I need SOME solution that is simple.
One problem I have had is with edit_inline and auto_now where the
entries are always updated in teh admin even if nothing was changed.
Also there are sometimes when I want an auto_now on condition. So this
all boils down to something like

def auto_now(save, *field_names, **options):
condition = None
if 'condition' in options: condition = options['condition']
if not len(field_names): raise InvalidArgument, "Something..."
save = save
field_names = field_names
def auto_now_decorator(object):
if condition is not None:
if not condition(object): return
for name in field_names:
setattr(object, name, datetime.datetime.now())
save(object)
return auto_now_decorator

def auto_add_now(save, *field_names, **options):
base_condition = None
if 'condition' in options:
base_condition = options['condition']
def new_condition(object):
## add code to get models PK field from type(object).
pk = 'id'
if getattr(object, pk) is None:
if base_condition is not None:
return base_condition(object)
return True
return False
options['condition'] = new_condition
return auto_now(save, *field_names, **options)

This would allow for things like:

@auto_now('last_saved_on', 'other_field')
@auto_now('updated_on', condition = lambda obj:
fields_have_changed(object))
## only set the datetime on new objects if the field is not already
set...
@auto_add_now('submitted_date', condition=lambda obj:
obj.submitted_date is None)
def save(self):
## some other custom code....
super(MyModel, self).save()

To be honest this could be abstracted further where the dynamic value
could be set lazy, (like in the previous post has on the model
fields).
I perfer having these as decorators so they can be added to ANY save
'like' method or on the form it's self.
I also used the term 'dynamic' on purpose, as this is not a default
value, but could be set to anything based on any of the other fields
or any outside influence.

There are problems with the above code, the PK issue is mentioned, but
there are also issued with time vs data vs datetime vs strings, and
giving proper errors for fields which do not exist.
I would also want another option for doing backoff validation but that
is for a separate post.
I would love any feedback anyone has on this Idea. There are a number
of projects I am working on that will need this (PyCon, python Jobs
board, and 3 others), so I plan on doing a formal implementation
starting soon.

-Doug

Reply all
Reply to author
Forward
0 new messages