Opened 16 months ago

Closed 16 months ago

Last modified 16 months ago

#21312 closed Uncategorized (invalid)

models.DateTimeField with default=now: South migration fails

Reported by: magopian Owned by: nobody
Component: Database layer (models, ORM) Version: 1.6-beta-1
Severity: Normal Keywords:
Cc: pronik Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

This is a problem that didn't happen on django1.6b4, but does on django1.6c1:

Here's a snippet of the model:

from django.utils.timezone import now


@python_2_unicode_compatible
class User(AbstractBaseUser, PermissionsMixin):
    """TopChretien User, identified by its email."""
    ...
    last_modified = models.DateTimeField(
        _('last modification'), default=now, editable=False)
    ...

Here's the auto migration created by South when adding this new field to the model:

import datetime
...

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding field 'User.last_modified'
        db.add_column(u'user_user', 'last_modified',
                      self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now),
                      keep_default=False)

And here's the result of running "manage.py migrate user" on django1.6b4:

$ ./manage.py migrate user
Running migrations for user:
 - Migrating forwards to 0007_auto__add_field_user_last_modified__add_field_user_moderation_date__ad.
 > user:0007_auto__add_field_user_last_modified__add_field_user_moderation_date__ad
/home/mathieu/.virtualenvs/top/lib/python2.7/site-packages/django/db/models/fields/__init__.py:901: RuntimeWarning: DateTimeField received a naive datetime (2013-10-23 15:50:11.448018) while time zone support is active.
  RuntimeWarning)

 - Loading initial data for user.
Installed 0 object(s) from 0 fixture(s)

And now on django1.6c1 (only the end of stacktrace, for readability, please let me know if you need more):

  File "/home/mathieu/Dropbox/dev/topchretien/web/topchretien/user/migrations/0007_auto__add_field_user_moderation_date__add_field_user_moderator__add_fi.py", line 14, in forwards
    keep_default=False)
  File "/home/mathieu/.virtualenvs/top/lib/python2.7/site-packages/south/db/generic.py", line 47, in _cache_clear
    return func(self, table, *args, **opts)
  File "/home/mathieu/.virtualenvs/top/lib/python2.7/site-packages/south/db/generic.py", line 411, in add_column
    sql = self.column_sql(table_name, name, field)
  File "/home/mathieu/.virtualenvs/top/lib/python2.7/site-packages/south/db/generic.py", line 706, in column_sql
    default = field.get_db_prep_save(default, connection=self._get_connection())
  File "/home/mathieu/.virtualenvs/top/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 350, in get_db_prep_save
    prepared=False)
  File "/home/mathieu/.virtualenvs/top/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 911, in get_db_prep_value
    value = self.get_prep_value(value)
  File "/home/mathieu/.virtualenvs/top/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 902, in get_prep_value
    (self.model.__name__, self.name, value),
AttributeError: 'DateTimeField' object has no attribute 'model'

The solution I used was to modify the South migration to get rid of the warning (in Django1.6b4) and make it work correctly (in django1.6c1):

import django.utils.timezone
...

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding field 'User.last_modified'
        db.add_column(u'user_user', 'last_modified',
                      self.gf('django.db.models.fields.DateTimeField')(default=django.utils.timezone.now),
                      keep_default=False)

Change History (7)

comment:1 Changed 16 months ago by mjtamlyn

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Severity changed from Normal to Release blocker
  • Version changed from 1.4 to 1.6-beta-1

I haven't checked this but marking as a release block as assuming it is repeatable it certainly is a problem.

Do you perhaps have a minimal project set up to reproduce this? If not, could you perhaps try to use git bisect to identify where between the tags it broke? This would help us identify a fix faster.

comment:2 Changed 16 months ago by akaariai

I've taken a quick look at this. This was introduced by ddff6522fa72aacc7475ba5cd4bf8683ff12b8c7. The problem is that South doesn't assign the field to any model. In Django self.model should always exists (or at least always after app-loading).

I am not sure if this should be fixed in Django or in South. We can definitely say that South relies on non-public usage of fields (after all the only public way to use fields is to assign them to models in model definition, and that means they will have self.model set). OTOH it seems pretty simple to fix this in Django... I have generally favoured "private API is private" -approach, so I am slightly in favour of that interpretation.

comment:3 Changed 16 months ago by shai

  • Component changed from Uncategorized to Database layer (models, ORM)
  • Severity changed from Release blocker to Normal

Based on Anssi's analysis, this is not a blocker for Django. Not sure it is even a bug in Django.

comment:4 Changed 16 months ago by pronik

  • Cc pronik added

comment:5 Changed 16 months ago by andrewgodwin

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

This is definitely a bug in South. Closing as invalid.

comment:6 follow-up: Changed 16 months ago by jvzammit@…

Did anyone report this in South? Thanks.

comment:7 in reply to: ↑ 6 Changed 16 months ago by jvzammit@…

Replying to jvzammit@…:

Did anyone report this in South? Thanks.

Please disregard my question; upgrading from south 0.8.2 to 0.8.3 solved the problem.

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