{{{
# -*- 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.
* needs_better_patch: => 0
* needs_docs: => 0
* needs_tests: => 0
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/20978#comment:1>
* 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>
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>
* 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>
* 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>
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>