Opened 9 years ago

Closed 7 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: master
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: UI/UX:

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@… 9 years ago.
Temporary fix

Download all attachments as: .zip

Change History (31)

comment:1 follow-up: Changed 9 years ago by titoo

Replacing the auto_now_add with:

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

Solves the problem.

comment:2 Changed 9 years ago by anonymous

  • Version set to 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 Changed 9 years ago by anonymous

  • Cc brice.carpentier@… added

comment:4 Changed 9 years ago by Brian Ray <bray@…>

  • 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 Changed 9 years ago by jan

  • Cc djangodev@… added
  • priority changed from normal to high

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 Changed 9 years ago by Ido

  • Cc root.lastnode@… added
  • Component changed from Admin interface to Database wrapper
  • Severity changed from normal to major

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 Changed 9 years ago by asmodai@…

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 Changed 9 years ago by Ido

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 Changed 9 years ago by Pete Crosier

  • 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).

Changed 9 years ago by yk4ever@…

Temporary fix

comment:10 Changed 9 years ago by yk4ever@…

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 Changed 8 years ago by bjorn@…

  • Cc bjorn@… chengqi@… added

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

comment:12 Changed 8 years ago by Gary Wilson <gary.wilson@…>

  • Cc gary.wilson@… added

comment:15 Changed 8 years ago by Jyrki Pulliainen <jyrki.pulliainen@…>

  • 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 Changed 8 years ago by anonymous

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

comment:17 Changed 8 years ago by anonymous

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

comment:18 Changed 8 years ago by anonymous

  • Cc matt.barry@… added

comment:19 Changed 8 years ago by Gary Wilson <gary.wilson@…>

  • Component changed from Database wrapper to Admin interface
  • Has patch set
  • Needs tests set
  • Patch needs improvement set
  • Summary changed from auto_now_add is broken for inline edited field to auto_now_add is broken for edit_inline field
  • Triage Stage changed from Unreviewed to Accepted

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

comment:20 Changed 8 years ago by brooks.travis@…

  • 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 follow-up: Changed 8 years ago by SmileyChris

  • Resolution set to fixed
  • Status changed from new to closed

auto_now and auto_now_add have been removed altogether

comment:22 in reply to: ↑ 21 ; follow-up: Changed 8 years ago by ubernostrum

  • Resolution fixed deleted
  • Status changed from closed to reopened

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 :(

comment:23 in reply to: ↑ 22 Changed 8 years ago by SmileyChris

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 Changed 8 years ago by anonymous

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.

comment:25 in reply to: ↑ 1 ; follow-up: Changed 8 years ago by drbob@…

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?

comment:26 in reply to: ↑ 25 ; follow-up: Changed 8 years ago by gwilson

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 Changed 7 years ago by Scott Moonen <smoonen@…>

  • 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.

comment:29 in reply to: ↑ 26 Changed 7 years ago by lukeplant

Replying to gwilson:

That should be:

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

comment:30 Changed 7 years ago by brosner

  • Resolution set to invalid
  • Status changed from reopened to closed

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