[Django] #25129: Migration crash on ForeignKey with a callable default that returns a model instance

25 views
Skip to first unread message

Django

unread,
Jul 15, 2015, 4:23:42 PM7/15/15
to django-...@googlegroups.com
#25129: Migration crash on ForeignKey with a callable default that returns a model
instance
--------------------------------------+------------------------
Reporter: timgraham | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.8
Severity: Normal | Keywords:
Triage Stage: Accepted | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------+------------------------
For example, this model in Django's test suite (from
`tests/delete/models.py`):
{{{#!python
class R(models.Model):
is_default = models.BooleanField(default=False)

def get_default_r():
return R.objects.get_or_create(is_default=True)[0]

class A(models.Model):
setdefault = models.ForeignKey(R, default=get_default_r)
}}}
will fail like this:
{{{
File "/home/tim/code/django/django/db/migrations/migration.py", line
123, in apply
operation.database_forwards(self.app_label, schema_editor, old_state,
project_state)
File "/home/tim/code/django/django/db/migrations/operations/fields.py",
line 62, in database_forwards
field,
File "/home/tim/code/django/django/db/backends/sqlite3/schema.py", line
224, in add_field
self._remake_table(model, create_fields=[field])
File "/home/tim/code/django/django/db/backends/sqlite3/schema.py", line
104, in _remake_table
self.effective_default(field)
File "/home/tim/code/django/django/db/backends/base/schema.py", line
214, in effective_default
default = field.get_db_prep_save(default, self.connection)
File "/home/tim/code/django/django/db/models/fields/related.py", line
2017, in get_db_prep_save
return self.target_field.get_db_prep_save(value,
connection=connection)
File "/home/tim/code/django/django/db/models/fields/__init__.py", line
721, in get_db_prep_save
prepared=False)
File "/home/tim/code/django/django/db/models/fields/__init__.py", line
969, in get_db_prep_value
value = self.get_prep_value(value)
File "/home/tim/code/django/django/db/models/fields/__init__.py", line
977, in get_prep_value
return int(value)
TypeError: int() argument must be a string or a number, not 'R'
}}}
The issue is that
[https://github.com/django/django/blob/c52822e7501e8478abf99465d8c9f3102dde618a/django/db/models/fields/related.py#L2003-L2008
ForeignKey.get_default()] doesn't return the model instance's ID because
`self.remote_field.model` is `<class '__fake__.R'>` when migrating while
the default function returns a "real" model instance.

--
Ticket URL: <https://code.djangoproject.com/ticket/25129>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 15, 2015, 6:33:05 PM7/15/15
to django-...@googlegroups.com
#25129: Migration crash on ForeignKey with a callable default that returns a model
instance
----------------------------+------------------------------------

Reporter: timgraham | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.8
Severity: Normal | Resolution:

Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+------------------------------------

Comment (by charettes):

Since no arguments are passed to the default value callable we've got two
options:

1. Document that foreign key callable defaults must return the value of
the field they reference (`pk` unless `to_field` is set).
2. Change the check in `ForeignKey.get_default()` to
`instance(field_default, models.Model) and field_default._meta.label ==
self.remote_field.model._meta.label`.

I'd favor the first option.

--
Ticket URL: <https://code.djangoproject.com/ticket/25129#comment:1>

Django

unread,
Jul 16, 2015, 8:26:55 AM7/16/15
to django-...@googlegroups.com
#25129: Migration crash on ForeignKey with a callable default that returns a model
instance
----------------------------+------------------------------------

Reporter: timgraham | Owner: nobody
Type: Bug | Status: new
Component: Migrations | Version: 1.8
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+------------------------------------
Changes (by timgraham):

* has_patch: 0 => 1


Comment:

Option 1 seems okay to me. It's the second commit in this
[https://github.com/django/django/pull/5003 pull request].

--
Ticket URL: <https://code.djangoproject.com/ticket/25129#comment:2>

Django

unread,
Jul 21, 2015, 9:20:12 AM7/21/15
to django-...@googlegroups.com
#25129: Migration crash on ForeignKey with a callable default that returns a model
instance
----------------------------+------------------------------------
Reporter: timgraham | Owner: nobody
Type: Bug | Status: closed
Component: Migrations | Version: 1.8
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: new => closed
* resolution: => fixed


Comment:

In [changeset:"b60375d4bbb848af7950379e2f35a1a65f7a2591" b60375d4]:
{{{
#!CommitTicketReference repository=""
revision="b60375d4bbb848af7950379e2f35a1a65f7a2591"
Fixed #25129 -- Made model instance defaults work with migrations (refs
#24919).
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/25129#comment:3>

Reply all
Reply to author
Forward
0 new messages