Opened 18 years ago

Closed 16 years ago

#1030 closed defect (invalid)

auto_now_add is broken for edit_inline field

Reported by: titoo Owned by: nobody
Component: contrib.admin Version: dev
Severity: major Keywords:
Cc: ibonso@…, brice.carpentier@…, bray@…, djangodev@…, root.lastnode@…, pete.crosier@…, bjorn@…, chengqi@…, gary.wilson@…, jyrki.pulliainen@…, matt.barry@…, brooks.travis@…, smoonen@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: yes Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

Considering the following models:

from django.core import meta

class Testcontact(meta.Model):
    name = meta.CharField(maxlength=100)
    birth_date = meta.DateField(blank=True, null=True)
    time_added = meta.DateTimeField(auto_now_add=True)
    time_modified = meta.DateTimeField(auto_now=True)

    def __repr__(self):
        return self.name

    class META:
        admin = meta.Admin()

class Testaddress(meta.Model):
    email = meta.EmailField(core=True)
    time_added = meta.DateTimeField(auto_now_add=True)
    time_modified = meta.DateTimeField(auto_now=True)
    contact = meta.ForeignKey(Testcontact, edit_inline=meta.STACKED, min_num_in_admin=2)

    def __repr__(self):
        return self.email

When adding a "contact" as long as no emails are provided, everything is fine. Then if you add an email, the first save is ok, the second one will return an error:

Request Method: POST
Request URL: http://127.0.0.1:8000/admin/testcase/testcontacts/1/
Exception Type: OperationalError
Exception Value: testcase_testaddresss.time_added may not be NULL
Exception Location: /usr/lib/python2.4/site-packages/django/core/db/backends/sqlite3.py in execute, line 71

As shown the backend is sqlite, django revision 1568.

Attachments (1)

django_1030.patch (788 bytes ) - added by yk4ever@… 18 years ago.
Temporary fix

Download all attachments as: .zip

Change History (31)

comment:1 by titoo, 18 years ago

Replacing the auto_now_add with:

time_added = meta.DateTimeField(default=meta.LazyDate(), blank=True, editable=False)

Solves the problem.

comment:2 by anonymous, 18 years ago

Version: SVN

I can reproduce this error with this model and django revision 2279, also sqlite backend :

class File(meta.Model):
    """This class manages a File object
       This basically add some metadata to a FielField"""

    title = meta.CharField(maxlength=50)
    slug = meta.SlugField(prepopulate_from=('title',))
    description = meta.TextField(maxlength=255)
    # creation_date should receive auto_now_add, but it seems to interact
    # weirdly with FileField
    creation_date = meta.DateTimeField(auto_now_add=True)
    modification_date = meta.DateTimeField(auto_now=True)
    file = meta.FileField(upload_to='files/%Y/%m/')

The error is nearly the same. Only the field's name is (obviously) different.
Note that there's no error if I remomve the "_add" from the "creation_date" field OR if I comment the "file" field out (and reset the database)

comment:3 by anonymous, 18 years ago

Cc: brice.carpentier@… added

comment:4 by Brian Ray <bray@…>, 18 years ago

Cc: bray@… added

I see this also.

Here is my error query:

ERROR: null value in column "createdate" violates not-null constraint UPDATE "abc_inventoryitems" SET "groupcode"='SEA',"language"='',"description"='Core LHD',"itemcode"='9201.35',"printteam"=22200,"reportid_id"='1',"createdate"=NULL WHERE "id"='1'

and my model:

class InventoryItem(meta.Model):   
   groupcode = meta.CharField("Section Code",maxlength=10,help_text="Code for Section, ie ABX, SEA,...")   
   language = meta.CharField("Language", choices=LANGUAGES, null=True, maxlength=50, blank=True)   
   description = meta.CharField("Item Description",  maxlength=30, help_text="Short desciption, i.")   
   itemcode = meta.CharField("Unique Item Code", maxlength=30, help_text="Unique Vendor supplied code.")   
   printteam = meta.IntegerField("Printteam Code:", maxlength=6, help_text="Five digit printstream code")               
   reportid = meta.ForeignKey(InventoryReport, verbose_name="Inventory Item", edit_inline=meta.TABULAR,num_in_admin=10)   
   createdate = meta.DateTimeField("Created Date", auto_now_add=True)

Although the first time a added a bank of tabular entries it worked file. However, I get this error only when I add the 11th (after the first bank of ten was full). If I come back and try to add one, I still get this error.

-- Brian Ray <bray@…>

comment:5 by jan, 18 years ago

Cc: djangodev@… added
priority: normalhigh

Bug persists: Only occurs when adding a referenced object to an existing entry, i.e. adding a new mailbox to a domain. adding separately works, inline edit fails with database exception due to null-field

comment:6 by Ido, 18 years ago

Cc: root.lastnode@… added
Component: Admin interfaceDatabase wrapper
Severity: normalmajor

Bug persists into magic-removal branche too,
i get a sqlerror with this code:

new_child = manipulator.save(new_data)
parent.child_set.add(new_child)

where none on the auto_add* model.DateTimeFields are set in new_data
figuring that auto_add and auto_add_now (for creation and modification date)
will take care or those fields.

now the error: (only the header, using the sqlite backend)
Request Method: POST
Request URL: http://localhost/edit/parent/2/addChild/
Exception Type: OperationalError
Exception Value: children_child.cre_date may not be NULL
Exception Location: /usr/src/Django-trunk/django/db/backends/sqlite3/base.py in execute, line 73

changed properties:
component: admin -> database wrapper, cause my errors where in views.py not the admin pages
severity: normal -> major, cause i found that in many cases this defect renders auto_add(_now)
unusable (out of the box) for creation and modification fields.

comment:7 by asmodai@…, 18 years ago

Could you people try the current SVN trunk?

Luke Plant fixed something for auto_now_add which fixes the UPDATE after the initial INSERT TO to have the right datestamp and not a NULL value.

comment:8 by Ido, 18 years ago

i've quickly tested the code in svn trunk and it looks okey.
i'll be coding more on the model with lots of auto_now and auto_now_add functions
near the end of this week, if i'll find errors i'll post a comment here.

comment:9 by Pete Crosier, 18 years ago

Cc: pete.crosier@… added

Still reproduceable in current SVN, with the same experience as Brian above.

I'm showing 1 editable inline object (it seems Brian was showing 10), the first of which is created without a hitch. When I go back to create object number 2 (or in Brian's case, 11), it fails with a "null value in column "my_date_field" violates not-null constraint UPDATE.." (using PostgreSQL).

by yk4ever@…, 18 years ago

Attachment: django_1030.patch added

Temporary fix

comment:10 by yk4ever@…, 18 years ago

Problem located:
django_src/django/db/models/fields/init.py
DateField.get_follow()

This method returns True for auto_now_add fields - therefore, they are counted as enabled in admin section, and their value is overwritten by None.

Removing this method solves the bug, but I don't sure about side effects.

comment:11 by bjorn@…, 17 years ago

Cc: bjorn@… chengqi@… added

Adding myself and a colleague to the cc for this ticket. We're having this problem.

comment:12 by Gary Wilson <gary.wilson@…>, 17 years ago

Cc: gary.wilson@… added

comment:15 by Jyrki Pulliainen <jyrki.pulliainen@…>, 17 years ago

Cc: jyrki.pulliainen@… added

Easy bypass, without changing django source, for this is a custom save method:

def save(self):
    if self.id:
        this_object = Object.objects.filter(id__exact=self.id)[0]
        self.add_date = this_object.add_date
    super(Object, self).save()

This, however, overwrites the changes if the field is editable (probably not, if auto_add_now is used?)

comment:16 by anonymous, 17 years ago

Cc: ibonso@… added; brice.carpentier@… bray@… djangodev@… root.lastnode@… pete.crosier@… bjorn@… chengqi@… gary.wilson@… jyrki.pulliainen@… removed

comment:17 by anonymous, 17 years ago

Cc: brice.carpentier@… bray@… djangodev@… root.lastnode@… pete.crosier@… bjorn@… chengqi@… gary.wilson@… jyrki.pulliainen@… added

comment:18 by anonymous, 17 years ago

Cc: matt.barry@… added

comment:19 by Gary Wilson <gary.wilson@…>, 17 years ago

Component: Database wrapperAdmin interface
Has patch: set
Needs tests: set
Patch needs improvement: set
Summary: auto_now_add is broken for inline edited fieldauto_now_add is broken for edit_inline field
Triage Stage: UnreviewedAccepted

Changed summary to include "edit_inline". The patch is described as a temp fix.

comment:20 by brooks.travis@…, 17 years ago

Cc: brooks.travis@… added

I'm having a similar issue in a view I've recently created using newforms. When I try to modify an existing model object, I get the following error: "year is out of range". I'm using MySQL 5.0.22. I've gone into the DB tables themselves and checked the data. After the initial object creation, the create date is set properly. However, after any subsequent save/update of the object, the create date is set back to all zeroes. This DOES NOT occur in the admin interface, only in my custom view using the newforms save() method.

comment:21 by Chris Beaven, 17 years ago

Resolution: fixed
Status: newclosed

auto_now and auto_now_add have been removed altogether

in reply to:  21 ; comment:22 by James Bennett, 17 years ago

Resolution: fixed
Status: closedreopened

Replying to SmileyChris:

auto_now and auto_now_add have been removed altogether

Nope. Still kicking around, much to my chagrin. Check django/db/models/__init__.py to verify that they're still in the codebase :(

in reply to:  22 comment:23 by Chris Beaven, 17 years ago

Replying to ubernostrum:

Nope. Still kicking around, much to my chagrin. Check django/db/models/__init__.py to verify that they're still in the codebase :(

So shouldn't that be opened as a new ticket (perhaps referencing this one)? I'm sure the goal was to eliminate those.

comment:24 by anonymous, 17 years ago

Looked in django/db/models/fields/init.py and saw that DateField has the following get_follow() method:

    # Needed because of horrible auto_now[_add] behaviour wrt. editable
    def get_follow(self, override=None):
        if override != None:
            return override
        else:
            return self.editable or self.auto_now or self.auto_now_add

BUT, DateTimeField has the following get_follow() instead:

    def get_follow(self, override=None): 
        if override != None:
            return override
        else:
            return self.editable

Shouldn't they be the same? I have DateTimeFields with auto_add_now and they are causing the same problem described.

in reply to:  1 ; comment:25 by drbob@…, 17 years ago

Replying to titoo:

Replacing the auto_now_add with:

time_added = meta.DateTimeField(default=meta.LazyDate(), blank=True, editable=False)

LazyDate does not seem to be present at all in the current SVN nor does the posted patch work. Any suggestions?

in reply to:  25 ; comment:26 by Gary Wilson, 17 years ago

Replying to drbob@dokterbob.net:

LazyDate does not seem to be present at all in the current SVN nor does the posted patch work. Any suggestions?

LazyDate was removed a little while back. But now the default parameter takes callables, so you can do this:

from datetime import datetime
...
time_added = meta.DateTimeField(default=datetime.now(), blank=True, editable=False)

comment:27 by Scott Moonen <smoonen@…>, 16 years ago

Cc: smoonen@… added

I'm seeing this problem as well. I tracked it down to DateField.get_follow before finding this defect. Removing DateField.get_follow and allowing things to fallback to the Field.get_follow behavior fixes things for me.

in reply to:  26 comment:29 by Luke Plant, 16 years ago

Replying to gwilson:

That should be:

from datetime import datetime
...
time_added = meta.DateTimeField(default=datetime.now, blank=True, editable=False)

comment:30 by Brian Rosner, 16 years ago

Resolution: invalid
Status: reopenedclosed

edit_inline has been completely refactored from newforms-admin in 1.0. This likely works, aside from the state of auto_now_add. Marking invalid.

Note: See TracTickets for help on using tickets.
Back to Top