Opened 10 years ago
Closed 10 years ago
#25129 closed Bug (fixed)
Migration crash on ForeignKey with a callable default that returns a model instance
| Reported by: | Tim Graham | Owned by: | nobody |
|---|---|---|---|
| Component: | Migrations | Version: | 1.8 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
For example, this model in Django's test suite (from tests/delete/models.py):
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 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.
Change History (3)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
| Has patch: | set |
|---|
Option 1 seems okay to me. It's the second commit in this pull request.
Note:
See TracTickets
for help on using tickets.
Since no arguments are passed to the default value callable we've got two options:
pkunlessto_fieldis set).ForeignKey.get_default()toinstance(field_default, models.Model) and field_default._meta.label == self.remote_field.model._meta.label.I'd favor the first option.