Opened 8 months ago

Last modified 8 months ago

#30032 new New feature

Allow expressions to be used for default

Reported by: Gavin Wahl Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have this field:

    foo = models.DateTimeField(default=timezone.now)

I would like to modify it to use TransactionNow instead:

    foo = models.DateTimeField(default=TransactionNow())

This migration operation is generated:

        migrations.AlterField(
            model_name='somemodel',
            name='foo',
            field=models.DateTimeField(default=django.contrib.postgres.functions.TransactionNow()),
        ),

When run, this error is thrown:

  File "./manage.py", line 29, in <module>
    execute_from_command_line(sys.argv)
  File "django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "django/core/management/base.py", line 316, in run_from_argv
    self.execute(*args, **cmd_options)
  File "django/core/management/base.py", line 353, in execute
    output = self.handle(*args, **options)
  File "django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "django/core/management/commands/migrate.py", line 203, in handle
    fake_initial=fake_initial,
  File "django/db/migrations/executor.py", line 117, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "django/db/migrations/executor.py", line 147, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "django/db/migrations/executor.py", line 244, in apply_migration
    state = migration.apply(state, schema_editor)
  File "django/db/migrations/migration.py", line 124, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "django/db/migrations/operations/fields.py", line 216, in database_forwards
    schema_editor.alter_field(from_model, from_field, to_field)
  File "django/db/backends/base/schema.py", line 523, in alter_field
    old_db_params, new_db_params, strict)
  File "django/db/backends/postgresql/schema.py", line 122, in _alter_field
    new_db_params, strict,
  File "django/db/backends/base/schema.py", line 626, in _alter_field
    old_default = self.effective_default(old_field)
  File "django/db/backends/base/schema.py", line 239, in effective_default
    return field.get_db_prep_save(default, self.connection)
  File "django/db/models/fields/__init__.py", line 790, in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
  File "django/db/models/fields/__init__.py", line 1429, in get_db_prep_value
    value = self.get_prep_value(value)
  File "django/db/models/fields/__init__.py", line 1408, in get_prep_value
    value = super().get_prep_value(value)
  File "django/db/models/fields/__init__.py", line 1268, in get_prep_value
    return self.to_python(value)
  File "django/db/models/fields/__init__.py", line 1369, in to_python
    parsed = parse_datetime(value)
  File "django/utils/dateparse.py", line 106, in parse_datetime
    match = datetime_re.match(value)
TypeError: expected string or bytes-like object

If I create the field foo from scratch, with an AddField operation instead of AlterField, it works as expected.

I should be able to modify a field to use TransactionNow() as a default.

Change History (7)

comment:1 Changed 8 months ago by Simon Charette

Resolution: duplicate
Status: newclosed

Datebase level defaults are not supported yet, see #470.

comment:2 Changed 8 months ago by Gavin Wahl

This isn't a database level default, that ticket is to support defaults assigned by DDL. This is to support expressions as defaults.

comment:3 Changed 8 months ago by Simon Charette

Resolution: duplicate
Status: closednew
Summary: Can't alter the default of a DateTimeField to be TransactionNowAllow expressions to be used for default
Triage Stage: UnreviewedAccepted
Type: BugNew feature
Version: 2.1master

Sorry about the misinterpretation, #27222 seems related and I'm pretty sure there's another ticket related to allowing Now() to be used for default but I can't find it.

Tentatively accepting as a new feature request but as I said I'm pretty sure there is already another ticket tracking this.

comment:4 Changed 8 months ago by Tim Graham

Simon, you might be thinking of this PR which adds unofficial support for something like models.DateTimeField(default=Now) on PostgreSQL.

comment:5 Changed 8 months ago by Simon Charette

Thanks Tim, that's exactly what I had in mind. Should we close this ticket in favour of #29444 then?

comment:6 Changed 8 months ago by Tim Graham

I think we should keep this open as there will be more work to do even if that ticket is closed (adding support for other databases and making the support official with documentation).

comment:7 Changed 8 months ago by Simon Charette

Makes sense, thanks for chiming in.

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