[Django] #20978: Cannot migrate if on_delete=models.SET_NULL

8 views
Skip to first unread message

Django

unread,
Aug 26, 2013, 8:57:06 AM8/26/13
to django-...@googlegroups.com
#20978: Cannot migrate if on_delete=models.SET_NULL
----------------------------+--------------------
Reporter: MarkusH | Owner:
Type: Bug | Status: new
Component: Migrations | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+--------------------
Given the following models, the `migrate` step fails with `'module' object
has no attribute 'set_on_delete'`.

{{{
# -*- coding: utf-8 -*-
from django.db import models
from django.utils.encoding import python_2_unicode_compatible


@python_2_unicode_compatible
class MyModel(models.Model):
name = models.CharField('Name', max_length=50, unique=True)
text = models.TextField('Text', blank=True, null=True)

class Meta:
verbose_name = 'My “fancy” Model'
verbose_name_plural = 'My “fancy” Models'

def __str__(self):
return self.name


@python_2_unicode_compatible
class OtherModel(models.Model):
mymodel = models.ForeignKey(MyModel, null=True,
on_delete=models.SET_NULL)
value = models.IntegerField('Value', blank=True, null=False,
default=50)

class Meta:
verbose_name = 'Other Model'
verbose_name_plural = 'Other Models'

def __str__(self):
return '%(mymodel)s %(value)d' % {
'mymodel': self.mymodel.name,
'value': self.value,
}
}}}


The migration file looks like
{{{
# encoding: utf8
from django.db import models, migrations
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [(u'something', '0001_initial')]

operations = [
migrations.CreateModel(
fields = [(u'id', models.AutoField(verbose_name=u'ID',
serialize=False, auto_created=True, primary_key=True),), ('name',
models.CharField(unique=True, max_length=50, verbose_name='Name'),),
('text', models.TextField(null=True, verbose_name='Text', blank=True),)],
bases = (models.Model,),
options = {u'verbose_name': 'My \xe2\x80\x9cfancy\xe2\x80\x9d
Model', u'verbose_name_plural': 'My \xe2\x80\x9cfancy\xe2\x80\x9d
Models'},
name = 'MyModel',
),
migrations.CreateModel(
fields = [(u'id', models.AutoField(verbose_name=u'ID',
serialize=False, auto_created=True, primary_key=True),), ('mymodel',
models.ForeignKey(to=u'something.MyModel', to_field=u'id', null=True,
on_delete=django.db.models.deletion.set_on_delete),), ('value',
models.IntegerField(default=50, verbose_name='Value', blank=True),)],
bases = (models.Model,),
options = {u'verbose_name': 'Other Model',
u'verbose_name_plural': 'Other Models'},
name = 'OtherModel',
),
]
}}}


Migrating with Python 3.3:
{{{
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/markus/.venvs/django-master-
py3/src/django/django/core/management/__init__.py", line 397, in
execute_from_command_line
utility.execute()
File "/home/markus/.venvs/django-master-
py3/src/django/django/core/management/__init__.py", line 390, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/markus/.venvs/django-master-
py3/src/django/django/core/management/base.py", line 242, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/markus/.venvs/django-master-
py3/src/django/django/core/management/base.py", line 289, in execute
output = self.handle(*args, **options)
File "/home/markus/.venvs/django-master-
py3/src/django/django/core/management/commands/migrate.py", line 52, in
handle
executor = MigrationExecutor(connection,
self.migration_progress_callback)
File "/home/markus/.venvs/django-master-
py3/src/django/django/db/migrations/executor.py", line 14, in __init__
self.loader.load_disk()
File "/home/markus/.venvs/django-master-
py3/src/django/django/db/migrations/loader.py", line 77, in load_disk
migration_module = import_module("%s.%s" % (module_name,
migration_name))
File "/home/markus/.venvs/django-master-
py3/lib/python3.3/importlib/__init__.py", line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1586, in _gcd_import
File "<frozen importlib._bootstrap>", line 1567, in _find_and_load
File "<frozen importlib._bootstrap>", line 1534, in
_find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 586, in _check_name_wrapper
File "<frozen importlib._bootstrap>", line 1024, in load_module
File "<frozen importlib._bootstrap>", line 1005, in load_module
File "<frozen importlib._bootstrap>", line 562, in
module_for_loader_wrapper
File "<frozen importlib._bootstrap>", line 870, in _load_module
File "<frozen importlib._bootstrap>", line 313, in
_call_with_frames_removed
File "/home/markus/Coding/django-
testing/example/something/migrations/0001_initial.py", line 6, in <module>
class Migration(migrations.Migration):
File "/home/markus/Coding/django-
testing/example/something/migrations/0001_initial.py", line 20, in
Migration
fields = [('id', models.AutoField(serialize=False, auto_created=True,
primary_key=True, verbose_name='ID'),), ('mymodel',
models.ForeignKey(t_field='id',
on_delete=django.db.models.deletion.set_on_delete, null=True,
to='something.MyModel'),), ('value', models.IntegerField(default=50,
bank=True, verbose_name='Value'),)],
AttributeError: 'module' object has no attribute 'set_on_delete'
}}}


Migrating with Python 2.7.5:
{{{
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/markus/.venvs/django-master-
py27/src/django/django/core/management/__init__.py", line 397, in
execute_from_command_line
utility.execute()
File "/home/markus/.venvs/django-master-
py27/src/django/django/core/management/__init__.py", line 390, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/markus/.venvs/django-master-
py27/src/django/django/core/management/base.py", line 242, in
run_from_argv
self.execute(*args, **options.__dict__)
File "/home/markus/.venvs/django-master-
py27/src/django/django/core/management/base.py", line 289, in execute
output = self.handle(*args, **options)
File "/home/markus/.venvs/django-master-
py27/src/django/django/core/management/commands/migrate.py", line 52, in
handle
executor = MigrationExecutor(connection,
self.migration_progress_callback)
File "/home/markus/.venvs/django-master-
py27/src/django/django/db/migrations/executor.py", line 14, in __init__
self.loader.load_disk()
File "/home/markus/.venvs/django-master-
py27/src/django/django/db/migrations/loader.py", line 77, in load_disk
migration_module = import_module("%s.%s" % (module_name,
migration_name))
File "/usr/lib64/python2.7/importlib/__init__.py", line 37, in
import_module
__import__(name)
File "/home/markus/Coding/django-
testing/example/something/migrations/0001_initial.py", line 6, in <module>
class Migration(migrations.Migration):
File "/home/markus/Coding/django-
testing/example/something/migrations/0001_initial.py", line 18, in
Migration
fields = [(u'id', models.AutoField(verbose_name=u'ID',
serialize=False, auto_created=True, primary_key=True),), ('mymodel',
models.ForeignKey(to=u'something.MyModel', to_field=u'id', null=True,
on_delete=django.db.models.deletion.set_on_delete),), ('value',
models.IntegerField(default=50, verbose_name='Value', blank=True),)],
AttributeError: 'module' object has no attribute 'set_on_delete'
}}}

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

Django

unread,
Aug 27, 2013, 10:34:44 AM8/27/13
to django-...@googlegroups.com
#20978: Cannot migrate if on_delete=models.SET_NULL
----------------------------+------------------------------------

Reporter: MarkusH | Owner:
Type: Bug | Status: new
Component: Migrations | Version: master
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
----------------------------+------------------------------------
Changes (by timo):

* needs_better_patch: => 0
* needs_docs: => 0
* needs_tests: => 0
* stage: Unreviewed => Accepted


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

Django

unread,
Sep 1, 2013, 2:35:13 PM9/1/13
to django-...@googlegroups.com
#20978: Cannot migrate if on_delete=models.SET_NULL
----------------------------+------------------------------------

Reporter: MarkusH | Owner:
Type: Bug | Status: new
Component: Migrations | Version: master
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 loic84):

* has_patch: 0 => 1


Comment:

PR https://github.com/django/django/pull/1542.

This fixes the particular case of `SET_NULL` which should be a pretty
common case.

That said the underlying problem remains for `SET` which relies on a
closure, the serialization system is not going to like closure in general.
Maybe the value passed to `SET` should be stored on the field itself so it
can be recovered, just like `SET_DEFAULT` relies on `field.get_default()`.

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

Django

unread,
Sep 1, 2013, 3:27:20 PM9/1/13
to django-...@googlegroups.com
#20978: Cannot migrate if on_delete=models.SET_NULL
----------------------------+------------------------------------

Reporter: MarkusH | Owner:
Type: Bug | Status: new
Component: Migrations | Version: master
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
----------------------------+------------------------------------

Comment (by MarkusH):

Yeah, your solution obviously works, but is more a workaround than a fix.
That said, I'm actually not happy with this patch and would like to either
change the ticket to cover closures in general and provide a proper patch
or close this issue and open a new one covering the general problem.

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

Django

unread,
Sep 2, 2013, 2:04:53 AM9/2/13
to django-...@googlegroups.com
#20978: Cannot migrate if on_delete=models.SET_NULL
----------------------------+------------------------------------
Reporter: MarkusH | Owner: loic84
Type: Bug | Status: assigned
Component: Migrations | Version: master

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 loic84):

* owner: => loic84
* status: new => assigned


Comment:

Updated the PR with a generic solution for closures.

--
Ticket URL: <https://code.djangoproject.com/ticket/20978#comment:4>

Django

unread,
Sep 10, 2013, 10:22:09 AM9/10/13
to django-...@googlegroups.com
#20978: Cannot migrate if on_delete=models.SET_NULL
----------------------------+------------------------------------
Reporter: MarkusH | Owner: loic84
Type: Bug | Status: closed
Component: Migrations | Version: master
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: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"5df8f749e6338c85a091f41803e6ecb280fc9f70"]:
{{{
#!CommitTicketReference repository=""
revision="5df8f749e6338c85a091f41803e6ecb280fc9f70"
Fixed #20978 -- Made deletion.SET_NULL more friendly for
MigrationWriter.serialize.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/20978#comment:5>

Django

unread,
Sep 10, 2013, 10:22:09 AM9/10/13
to django-...@googlegroups.com
#20978: Cannot migrate if on_delete=models.SET_NULL
----------------------------+------------------------------------
Reporter: MarkusH | Owner: loic84
Type: Bug | Status: closed
Component: Migrations | Version: master

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
----------------------------+------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"d59f1993f150f83524051d96b52df08da4dcf011"]:
{{{
#!CommitTicketReference repository=""
revision="d59f1993f150f83524051d96b52df08da4dcf011"
Made MigrationWriter look for a "deconstruct" attribute on functions.

Refs #20978.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/20978#comment:6>

Reply all
Reply to author
Forward
0 new messages