Ticket #436 (closed defect: fixed)
Migration Fails with Proxy Model
| Reported by: | physicsrob@… | Owned by: | andrew |
|---|---|---|---|
| Priority: | major | Milestone: | 0.7.1 |
| Component: | commands | Version: | 0.7 |
| Keywords: | Cc: |
Description
It appears that there is a problem migrating applications that have a model with a foreignkey pointing to a proxy for django's User model.
Here is the example I'm trying with:
class MyUser?(User):
class Meta:
proxy=True
class MyModel?(models.Model):
user = models.ForeignKey?(MyUser?)
If you try to create a migration for this application you will get a failure:
south.exceptions.ORMBaseNotIncluded: Cannot find ORM base auth.user
I'm very new to south, so excuse my poor explanation, but it appears that the problem is in the migration's 'models' dictionary. It seems that there needs to be an entry for 'auth.user', but that never gets added.
Fortunately there is a workaround. If you add a dummy table to the application with a ForeignKey? on the User, south will properly add the 'auth.user' entry to the migrations 'models' dictionary.
e.g.:
class MyWorkaround?(models.Model):
user = models.ForeignKey?(User)
Attachments
Change History
Changed 3 years ago by physicsrob@…
- Attachment south_fix436.patch added
comment:1 Changed 3 years ago by physicsrob@…
I've created a patch that fixes this problem. Please review it thoroughly to make sure it makes sense.
Basically what I found was that model_dependencies (in freezer.py) was not correctly including dependencies to base classes. It was only adding base classes as dependencies if the base class is an instance of models.Model. This will only be true if the base class IS models.Model.
I updated the code by essentially replacing isinstance with issubclass. So now any base classes that are models will be included as dependencies. Which I believe is the correct behavior.
Let me know your thoughts!
Cheers,
Rob
Changed 3 years ago by physicsrob@…
- Attachment south_fix436_second_try.patch added
patch to fix problem
comment:2 Changed 3 years ago by physicsrob@…
Oops! The first patch I attached had a mistake. This one should be good!
comment:3 Changed 3 years ago by andrew
- Status changed from new to closed
- Resolution set to fixed
- Milestone set to 0.7.1
Yes, that's exactly the fix, thanks! Committed in [0505afae2906].
comment:4 Changed 3 years ago by kostia <kostia.lopuhin@…>
There is another related problem, not shure if it's worth a separate ticket: when there is a ManyToMany? field, that references proxy model:
If you define models in southtest application like this:
class ModelA(models.Model):
pass
class ProxyModel(ModelA):
class Meta:
proxy = True
class ModelB(models.Model):
modela_list = models.ManyToManyField(ProxyModel)
than create initial migration, you will get the following error when trying to apply it:
kostia@kostia-laptop:~/chtd/mcxgp$ python manage.py schemamigration southtest --initial
Creating migrations directory at '/home/kostia/chtd/mcxgp/southtest/migrations'...
Creating __init__.py in '/home/kostia/chtd/mcxgp/southtest/migrations'...
+ Added model southtest.ModelA
+ Added model southtest.ModelB
+ Added M2M table for modela_list on southtest.ModelB
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate southtest
kostia@kostia-laptop:~/chtd/mcxgp$ python manage.py migrate southtest
Running migrations for southtest:
- Migrating forwards to 0001_initial.
> southtest:0001_initial
Traceback (most recent call last):
File "manage.py", line 17, in <module>
execute_manager(settings)
File "/home/kostia/chtd/lib/django/core/management/__init__.py", line 438, in execute_manager
utility.execute()
File "/home/kostia/chtd/lib/django/core/management/__init__.py", line 379, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/kostia/chtd/lib/django/core/management/base.py", line 195, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/kostia/chtd/lib/django/core/management/base.py", line 222, in execute
output = self.handle(*args, **options)
File "/home/kostia/chtd/lib/south/management/commands/migrate.py", line 109, in handle
ignore_ghosts = ignore_ghosts,
File "/home/kostia/chtd/lib/south/migration/__init__.py", line 202, in migrate_app
success = migrator.migrate_many(target, workplan, database)
File "/home/kostia/chtd/lib/south/migration/migrators.py", line 220, in migrate_many
result = migrator.__class__.migrate_many(migrator, target, migrations, database)
File "/home/kostia/chtd/lib/south/migration/migrators.py", line 291, in migrate_many
result = self.migrate(migration, database)
File "/home/kostia/chtd/lib/south/migration/migrators.py", line 125, in migrate
result = self.run(migration)
File "/home/kostia/chtd/lib/south/migration/migrators.py", line 99, in run
return self.run_migration(migration)
File "/home/kostia/chtd/lib/south/migration/migrators.py", line 82, in run_migration
south.db.db.execute_deferred_sql()
File "/home/kostia/chtd/lib/south/db/generic.py", line 168, in execute_deferred_sql
self.execute(sql)
File "/home/kostia/chtd/lib/south/db/generic.py", line 134, in execute
cursor.execute(sql, params)
File "/home/kostia/chtd/lib/django/db/backends/util.py", line 20, in execute
return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: column "modela_ptr_id" referenced in foreign key constraint does not exist
using python 2.6.5, Django version 1.2 alpha 1 SVN-4476, postgresql-8.4
the problem is in generated migration, specificaly if you change this
# Adding M2M table for field modela_list on 'ModelB'
db.create_table('southtest_modelb_modela_list', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('modelb', models.ForeignKey(orm['southtest.modelb'], null=False)),
('proxymodel', models.ForeignKey(orm['southtest.proxymodel'], null=False))
))
db.create_unique('southtest_modelb_modela_list', ['modelb_id', 'proxymodel_id'])
to this
# Adding M2M table for field modela_list on 'ModelB'
db.create_table('southtest_modelb_modela_list', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('modelb', models.ForeignKey(orm['southtest.modelb'], null=False)),
('proxymodel', models.ForeignKey(orm['southtest.modela'], null=False))
))
db.create_unique('southtest_modelb_modela_list', ['modelb_id', 'proxymodel_id'])
(so that relation is with modela, not proxymodel, keeping field names the same) - than the migration runs smoothly. I'm not quite shure that this is a universall and even proper fix, but seems to work for me.
comment:5 follow-up: ↓ 6 Changed 3 years ago by andrew
Yes, that's really worthy of a separate bug - could you re-file it? The fix shouldn't be too hard, I hope.
comment:6 in reply to: ↑ 5 Changed 3 years ago by kostia.lopuhin@…
Replying to andrew:
Yes, that's really worthy of a separate bug - could you re-file it? The fix shouldn't be too hard, I hope.
Thanx! Refiled it as http://south.aeracode.org/ticket/496
comment:7 follow-up: ↓ 8 Changed 18 months ago by benjaoming@…
Hi!
I just tried to add a proxy table for the User model. ./manage.py schemamigration appname then created the following wrong migration script:
db.create_table('auth_user', (
,
))
...which I had to comment out. After that, everything worked fine. Am using South 0.7.3.
comment:8 in reply to: ↑ 7 Changed 18 months ago by andrew
Replying to benjaoming@…:
Hi!
I just tried to add a proxy table for the User model. ./manage.py schemamigration appname then created the following wrong migration script:
If you have a problem, please:
- Re-test using the South development version
- Open a bug, attaching the models file and the generated migration file

patch to fix problem