#23418 closed Cleanup/optimization (fixed)
Classes embedded inside other classes are not serialized correctly
| Reported by: | Dan Loewenherz | Owned by: | Markus Holtermann | 
|---|---|---|---|
| Component: | Migrations | Version: | 1.7 | 
| Severity: | Normal | Keywords: | |
| Cc: | info+coding@… | Triage Stage: | Unreviewed | 
| Has patch: | yes | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description
Simple example:
class Store(models.Model):
    @deconstructible
    class IgnoreFormatString(object):
        def __init__(self, s):
            self.s = s
        def __str__(self):
            return self.s
        def __mod__(self, k):
            return self
    name = models.CharField(max_length=64, null=True)
    rating = models.IntegerField(error_messages={'invalid': IgnoreFormatString("You've entered an invalid value.")}, null=True)
The migration is created appropriately, but running it will fail with something like the following:
Traceback (most recent call last):
  File "./manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "my_project/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File "my_project/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "my_project/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "my_project/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File "my_project/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 63, in handle
    executor = MigrationExecutor(connection, self.migration_progress_callback)
  File "my_project/lib/python2.7/site-packages/django/db/migrations/executor.py", line 17, in __init__
    self.loader = MigrationLoader(self.connection)
  File "my_project/lib/python2.7/site-packages/django/db/migrations/loader.py", line 48, in __init__
    self.build_graph()
  File "my_project/lib/python2.7/site-packages/django/db/migrations/loader.py", line 173, in build_graph
    self.load_disk()
  File "my_project/lib/python2.7/site-packages/django/db/migrations/loader.py", line 103, in load_disk
    migration_module = import_module("%s.%s" % (module_name, migration_name))
  File "/usr/local/Cellar/python/2.7.6/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "my_project/app/migrations/0001_initial.py", line 8, in <module>
    class Migration(migrations.Migration):
  File "my_project/app/migrations/0001_initial.py", line 19, in Migration
    ('rating', models.IntegerField(null=True, error_messages={b'invalid': app.models.IgnoreFormatString(b"You've entered an invalid value.")})),
AttributeError: 'module' object has no attribute 'IgnoreFormatString
Let me know if you need anything else to help diagnose the issue or have any questions. Cheers!
Change History (13)
comment:1 by , 11 years ago
| Resolution: | → invalid | 
|---|---|
| Status: | new → closed | 
comment:4 by , 11 years ago
@Andrew Any way we can prevent the migration itself from being created as well? Although the docs mention it now, the migration is still created and users won't encounter the error until after running it. Thoughts?
comment:5 by , 11 years ago
| Resolution: | invalid | 
|---|---|
| Status: | closed → new | 
Reopening since I'm not convinced a doc-only change is sufficient. I'm happy to contribute a patch if needed.
comment:6 by , 11 years ago
| Cc: | added | 
|---|---|
| Has patch: | set | 
| Owner: | changed from to | 
| Status: | new → assigned | 
| Type: | Bug → Cleanup/optimization | 
I opened a pull-request: https://github.com/django/django/pull/3194
comment:8 by , 11 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | assigned → closed | 
Unfortunately, this is unserializable, as there's no way to get the reference to the surrounding class from the inner class. I'll update the docs to mention this, but the only fix for you is to move InvalidFormatString to the outer scope.